(メッセージはありません)
@@ -902,6 +902,10 @@ | ||
902 | 902 | int cs_mount_permission(const char *dev_name, const struct path *path, |
903 | 903 | const char *type, unsigned long flags, |
904 | 904 | void *data_page); |
905 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
906 | +int cs_move_mount_permission(const struct path *from_path, | |
907 | + const struct path *to_path); | |
908 | +#endif | |
905 | 909 | int cs_pivot_root_permission(const struct path *old_path, |
906 | 910 | const struct path *new_path); |
907 | 911 | int cs_rename_permission(const struct path *old, const struct path *new); |
@@ -996,7 +996,23 @@ | ||
996 | 996 | return cs_mount_permission(dev_name, path, type, flags, data_page); |
997 | 997 | } |
998 | 998 | |
999 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
999 | 1000 | /** |
1001 | + * cs_move_mount - Check permission for move_mount(). | |
1002 | + * | |
1003 | + * @from_path: Pointer to "struct path". | |
1004 | + * @to_path: Pointer to "struct path". | |
1005 | + * | |
1006 | + * Returns 0 on success, negative value otherwise. | |
1007 | + */ | |
1008 | +static int cs_move_mount(const struct path *from_path, | |
1009 | + const struct path *to_path) | |
1010 | +{ | |
1011 | + return cs_move_mount_permission(from_path, to_path); | |
1012 | +} | |
1013 | +#endif | |
1014 | + | |
1015 | +/** | |
1000 | 1016 | * cs_sb_umount - Check permission for umount(). |
1001 | 1017 | * |
1002 | 1018 | * @mnt: Pointer to "struct vfsmount". |
@@ -1059,6 +1075,9 @@ | ||
1059 | 1075 | MY_HOOK_INIT(file_ioctl, cs_file_ioctl), |
1060 | 1076 | MY_HOOK_INIT(sb_pivotroot, cs_sb_pivotroot), |
1061 | 1077 | MY_HOOK_INIT(sb_mount, cs_sb_mount), |
1078 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
1079 | + MY_HOOK_INIT(move_mount, cs_move_mount), | |
1080 | +#endif | |
1062 | 1081 | MY_HOOK_INIT(sb_umount, cs_sb_umount), |
1063 | 1082 | #ifdef CONFIG_SECURITY_PATH |
1064 | 1083 | MY_HOOK_INIT(path_mknod, cs_path_mknod), |
@@ -1123,7 +1123,23 @@ | ||
1123 | 1123 | return cs_mount_acl(dev_name, path, type, flags, data_page); |
1124 | 1124 | } |
1125 | 1125 | |
1126 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
1126 | 1127 | /** |
1128 | + * cs_move_mount_permission - Check permission for move_mount() operation. | |
1129 | + * | |
1130 | + * @from_path: Pointer to "struct path". | |
1131 | + * @to_path: Pointer to "struct path". | |
1132 | + * | |
1133 | + * Returns 0 on success, negative value otherwise. | |
1134 | + */ | |
1135 | +int cs_move_mount_permission(const struct path *from_path, | |
1136 | + const struct path *to_path) | |
1137 | +{ | |
1138 | + return -ENOSYS; /* For now. */ | |
1139 | +} | |
1140 | +#endif | |
1141 | + | |
1142 | +/** | |
1127 | 1143 | * cs_open_permission - Check permission for "read" and "write". |
1128 | 1144 | * |
1129 | 1145 | * @path: Pointer to "struct path". |
@@ -1150,6 +1166,9 @@ | ||
1150 | 1166 | if (d_is_dir(path->dentry)) |
1151 | 1167 | return 0; |
1152 | 1168 | #endif |
1169 | + /* Sockets can't be opened by open(). */ | |
1170 | + if (S_ISSOCK(d_inode(path->dentry)->i_mode)) | |
1171 | + return 0; | |
1153 | 1172 | r.obj.path[0] = *path; |
1154 | 1173 | if (!(cs_flags & CS_TASK_IS_IN_EXECVE)) |
1155 | 1174 | cs_check_auto_domain_transition(); |
@@ -1507,6 +1526,9 @@ | ||
1507 | 1526 | */ |
1508 | 1527 | int cs_getattr_permission(const struct path *path) |
1509 | 1528 | { |
1529 | + /* It is not safe to call cs_get_socket_name(). */ | |
1530 | + if (S_ISSOCK(d_inode(path->dentry)->i_mode)) | |
1531 | + return 0; | |
1510 | 1532 | return cs_path_perm(CS_MAC_GETATTR, path); |
1511 | 1533 | } |
1512 | 1534 |
@@ -1643,6 +1665,8 @@ | ||
1643 | 1665 | { |
1644 | 1666 | struct cs_inet_addr_info *i = &address->inet; |
1645 | 1667 | |
1668 | + if (addr_len < offsetofend(struct sockaddr, sa_family)) | |
1669 | + return 0; | |
1646 | 1670 | switch (addr->sa_family) { |
1647 | 1671 | case AF_INET6: |
1648 | 1672 | if (addr_len < SIN6_LEN_RFC2133) |
@@ -1720,6 +1744,8 @@ | ||
1720 | 1744 | { |
1721 | 1745 | struct cs_unix_addr_info *u = &address->unix0; |
1722 | 1746 | |
1747 | + if (addr_len < offsetofend(struct sockaddr, sa_family)) | |
1748 | + return 0; | |
1723 | 1749 | if (addr->sa_family != AF_UNIX) |
1724 | 1750 | return 0; |
1725 | 1751 | u->addr = ((struct sockaddr_un *) addr)->sun_path; |
@@ -7,6 +7,7 @@ | ||
7 | 7 | */ |
8 | 8 | |
9 | 9 | #include "caitsith.h" |
10 | + | |
10 | 11 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) |
11 | 12 | #include <linux/nsproxy.h> |
12 | 13 | #include <linux/mnt_namespace.h> |
@@ -462,12 +463,14 @@ | ||
462 | 463 | } |
463 | 464 | inode = d_backing_inode(sb->s_root); |
464 | 465 | /* |
465 | - * Use local name for "filesystems without rename() operation" | |
466 | - * or "path without vfsmount" or "absolute name is unavailable" | |
467 | - * cases. | |
466 | + * Use local name for "filesystems without rename() operation | |
467 | + * and device file" or "path without vfsmount" or "absolute | |
468 | + * name is unavailable" cases. | |
468 | 469 | */ |
469 | 470 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) |
470 | - if (!path->mnt || (inode->i_op && !inode->i_op->rename)) | |
471 | + if (!path->mnt || | |
472 | + (inode->i_op && !inode->i_op->rename && | |
473 | + !(sb->s_type->fs_flags & FS_REQUIRES_DEV))) | |
471 | 474 | pos = ERR_PTR(-EINVAL); |
472 | 475 | else { |
473 | 476 | /* Get absolute name for the rest. */ |
@@ -477,12 +480,15 @@ | ||
477 | 480 | } |
478 | 481 | #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) |
479 | 482 | if (!path->mnt || |
480 | - (!inode->i_op->rename && !inode->i_op->rename2)) | |
483 | + (!inode->i_op->rename && !inode->i_op->rename2 && | |
484 | + !(sb->s_type->fs_flags & FS_REQUIRES_DEV))) | |
481 | 485 | pos = ERR_PTR(-EINVAL); |
482 | 486 | else |
483 | 487 | pos = cs_get_absolute_path(path, buf, buf_len - 1); |
484 | 488 | #else |
485 | - if (!path->mnt || !inode->i_op->rename) | |
489 | + if (!path->mnt || | |
490 | + (!inode->i_op->rename && | |
491 | + !(sb->s_type->fs_flags & FS_REQUIRES_DEV))) | |
486 | 492 | pos = ERR_PTR(-EINVAL); |
487 | 493 | else |
488 | 494 | pos = cs_get_absolute_path(path, buf, buf_len - 1); |
@@ -78,6 +78,10 @@ | ||
78 | 78 | int (*mount_permission)(const char *dev_name, const struct path *path, |
79 | 79 | const char *type, unsigned long flags, |
80 | 80 | void *data_page); |
81 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
82 | + int (*move_mount_permission) (const struct path *from_path, | |
83 | + const struct path *to_path); | |
84 | +#endif | |
81 | 85 | int (*umount_permission)(struct vfsmount *mnt, int flags); |
82 | 86 | |
83 | 87 | _Bool(*lport_reserved) (const u16 port); /* Not implemented. */ |
@@ -186,6 +190,16 @@ | ||
186 | 190 | return func ? func(dev_name, path, type, flags, data_page) : 0; |
187 | 191 | } |
188 | 192 | |
193 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
194 | +static inline int ccs_move_mount_permission(const struct path *from_path, | |
195 | + const struct path *to_path) | |
196 | +{ | |
197 | + int (*func) (const struct path *, const struct path *) = | |
198 | + caitsith_ops.move_mount_permission; | |
199 | + return func ? func(from_path, to_path) : 0; | |
200 | +} | |
201 | +#endif | |
202 | + | |
189 | 203 | static inline int ccs_umount_permission(struct vfsmount *mnt, int flags) |
190 | 204 | { |
191 | 205 | int (*func)(struct vfsmount *, int) |
@@ -413,6 +427,14 @@ | ||
413 | 427 | return 0; |
414 | 428 | } |
415 | 429 | |
430 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
431 | +static inline int ccs_move_mount_permission(const struct path *from_path, | |
432 | + const struct path *to_path) | |
433 | +{ | |
434 | + return 0; | |
435 | +} | |
436 | +#endif | |
437 | + | |
416 | 438 | static inline int ccs_umount_permission(struct vfsmount *mnt, int flags) |
417 | 439 | { |
418 | 440 | return 0; |
@@ -59,6 +59,7 @@ | ||
59 | 59 | int ccs_path_unlink(const struct path *dir, struct dentry *dentry); |
60 | 60 | int ccs_sb_mount(const char *dev_name, const struct path *path, |
61 | 61 | const char *type, unsigned long flags, void *data); |
62 | +int ccs_move_mount(const struct path *from_path, const struct path *to_path); | |
62 | 63 | int ccs_sb_pivotroot(const struct path *old_path, const struct path *new_path); |
63 | 64 | #else |
64 | 65 | int ccs_path_chmod(struct path *path, umode_t mode); |
@@ -101,6 +102,13 @@ | ||
101 | 102 | { |
102 | 103 | return 0; |
103 | 104 | } |
105 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
106 | +static inline int ccs_move_mount(const struct path *from_path, | |
107 | + const struct path *to_path) | |
108 | +{ | |
109 | + return 0; | |
110 | +} | |
111 | +#endif | |
104 | 112 | static inline int ccs_sb_umount(struct vfsmount *mnt, int flags) |
105 | 113 | { |
106 | 114 | return 0; |
@@ -91,6 +91,15 @@ | ||
91 | 91 | #define current_fsgid() (current->fsgid) |
92 | 92 | #endif |
93 | 93 | |
94 | +#ifndef offsetofend | |
95 | +#define offsetofend(TYPE, MEMBER) \ | |
96 | + (offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER)) | |
97 | +#endif | |
98 | + | |
99 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) | |
100 | +#define d_inode(dentry) (dentry)->d_inode | |
101 | +#endif | |
102 | + | |
94 | 103 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) |
95 | 104 | |
96 | 105 | /** |
@@ -93,6 +93,13 @@ | ||
93 | 93 | return ccs_pivot_root_permission(old_path, new_path); |
94 | 94 | } |
95 | 95 | |
96 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
97 | +int ccs_move_mount(const struct path *from_path, const struct path *to_path) | |
98 | +{ | |
99 | + return ccs_move_mount_permission(from_path, to_path); | |
100 | +} | |
101 | +#endif | |
102 | + | |
96 | 103 | int ccs_path_unlink(const struct path *dir, struct dentry *dentry) |
97 | 104 | { |
98 | 105 | return ccs_unlink_permission(dentry, dir->mnt); |
@@ -245,6 +252,9 @@ | ||
245 | 252 | static struct security_hook_list caitsith_hooks[] = { |
246 | 253 | LSM_HOOK_INIT(settime, ccs_settime), |
247 | 254 | LSM_HOOK_INIT(sb_mount, ccs_sb_mount), |
255 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
256 | + LSM_HOOK_INIT(move_mount, ccs_move_mount), | |
257 | +#endif | |
248 | 258 | LSM_HOOK_INIT(sb_umount, ccs_sb_umount), |
249 | 259 | LSM_HOOK_INIT(sb_pivotroot, ccs_sb_pivotroot), |
250 | 260 | LSM_HOOK_INIT(inode_getattr, ccs_inode_getattr), |
@@ -152,6 +152,10 @@ | ||
152 | 152 | static int cs_mount_permission(const char *dev_name, const struct path *path, |
153 | 153 | const char *type, unsigned long flags, |
154 | 154 | void *data_page); |
155 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
156 | +static int cs_move_mount_permission(const struct path *from_path, | |
157 | + const struct path *to_path); | |
158 | +#endif | |
155 | 159 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) |
156 | 160 | static int cs_open_exec_permission(struct dentry *dentry, |
157 | 161 | struct vfsmount *mnt); |
@@ -1131,6 +1135,9 @@ | ||
1131 | 1135 | caitsith_ops.parse_table = cs_parse_table; |
1132 | 1136 | #endif |
1133 | 1137 | caitsith_ops.mount_permission = cs_mount_permission; |
1138 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
1139 | + caitsith_ops.move_mount_permission = cs_move_mount_permission; | |
1140 | +#endif | |
1134 | 1141 | #ifdef CONFIG_CAITSITH_CAPABILITY |
1135 | 1142 | caitsith_ops.capable = cs_capable; |
1136 | 1143 | caitsith_ops.socket_create_permission = cs_socket_create_permission; |
@@ -1362,6 +1369,22 @@ | ||
1362 | 1369 | return cs_mount_acl(dev_name, path, type, flags, data_page); |
1363 | 1370 | } |
1364 | 1371 | |
1372 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) | |
1373 | +/** | |
1374 | + * cs_move_mount_permission - Check permission for move_mount() operation. | |
1375 | + * | |
1376 | + * @from_path: Pointer to "struct path". | |
1377 | + * @to_path: Pointer to "struct path". | |
1378 | + * | |
1379 | + * Returns 0 on success, negative value otherwise. | |
1380 | + */ | |
1381 | +static int cs_move_mount_permission(const struct path *from_path, | |
1382 | + const struct path *to_path) | |
1383 | +{ | |
1384 | + return -ENOSYS; /* For now. */ | |
1385 | +} | |
1386 | +#endif | |
1387 | + | |
1365 | 1388 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32) |
1366 | 1389 | |
1367 | 1390 | /** |
@@ -1424,6 +1447,9 @@ | ||
1424 | 1447 | if (d_is_dir(path->dentry)) |
1425 | 1448 | return 0; |
1426 | 1449 | #endif |
1450 | + /* Sockets can't be opened by open(). */ | |
1451 | + if (S_ISSOCK(d_inode(path->dentry)->i_mode)) | |
1452 | + return 0; | |
1427 | 1453 | r.obj.path[0] = *path; |
1428 | 1454 | if (!(cs_flags & CS_TASK_IS_IN_EXECVE)) |
1429 | 1455 | cs_check_auto_domain_transition(); |
@@ -1844,6 +1870,9 @@ | ||
1844 | 1870 | { |
1845 | 1871 | struct path path = { .mnt = mnt, .dentry = dentry }; |
1846 | 1872 | |
1873 | + /* It is not safe to call cs_get_socket_name(). */ | |
1874 | + if (S_ISSOCK(d_inode(dentry)->i_mode)) | |
1875 | + return 0; | |
1847 | 1876 | return cs_path_perm(CS_MAC_GETATTR, &path); |
1848 | 1877 | } |
1849 | 1878 |
@@ -2121,6 +2150,8 @@ | ||
2121 | 2150 | { |
2122 | 2151 | struct cs_inet_addr_info *i = &address->inet; |
2123 | 2152 | |
2153 | + if (addr_len < offsetofend(struct sockaddr, sa_family)) | |
2154 | + return 0; | |
2124 | 2155 | switch (addr->sa_family) { |
2125 | 2156 | case AF_INET6: |
2126 | 2157 | if (addr_len < SIN6_LEN_RFC2133) |
@@ -2199,6 +2230,8 @@ | ||
2199 | 2230 | { |
2200 | 2231 | struct cs_unix_addr_info *u = &address->unix0; |
2201 | 2232 | |
2233 | + if (addr_len < offsetofend(struct sockaddr, sa_family)) | |
2234 | + return 0; | |
2202 | 2235 | if (addr->sa_family != AF_UNIX) |
2203 | 2236 | return 0; |
2204 | 2237 | u->addr = ((struct sockaddr_un *) addr)->sun_path; |
@@ -2497,7 +2530,7 @@ | ||
2497 | 2530 | addr_len = u->len; |
2498 | 2531 | memcpy(&addr, u->name, addr_len); |
2499 | 2532 | } else { |
2500 | - addr_len = 0; | |
2533 | + addr_len = addr_len = sizeof(addr.ss_family); | |
2501 | 2534 | addr.ss_family = AF_UNIX; |
2502 | 2535 | } |
2503 | 2536 | if (cs_check_unix_address((struct sockaddr *) &addr, |
@@ -3600,7 +3633,11 @@ | ||
3600 | 3633 | goto done; |
3601 | 3634 | printk(KERN_WARNING "ERROR: Unable to transit to '%s' domain.\n", |
3602 | 3635 | r.transition->name); |
3636 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0) | |
3603 | 3637 | force_sig(SIGKILL, current); |
3638 | +#else | |
3639 | + force_sig(SIGKILL); | |
3640 | +#endif | |
3604 | 3641 | done: |
3605 | 3642 | cs_read_unlock(idx); |
3606 | 3643 | #endif |
@@ -344,6 +344,7 @@ | ||
344 | 344 | goto prepend_filesystem_name; |
345 | 345 | { |
346 | 346 | struct inode *inode = d_backing_inode(sb->s_root); |
347 | + | |
347 | 348 | /* |
348 | 349 | * Use filesystem name if filesystems does not support rename() |
349 | 350 | * operation. |
@@ -411,8 +412,7 @@ | ||
411 | 412 | if (sk) { |
412 | 413 | snprintf(buffer, buflen, |
413 | 414 | "socket:[family=%u:type=%u:protocol=%u]", |
414 | - sk->sk_family, sk->sk_type, | |
415 | - sk->sk_protocol); | |
415 | + sk->sk_family, sk->sk_type, sk->sk_protocol); | |
416 | 416 | } else { |
417 | 417 | snprintf(buffer, buflen, "socket:[unknown]"); |
418 | 418 | } |
@@ -463,12 +463,14 @@ | ||
463 | 463 | } |
464 | 464 | inode = d_backing_inode(sb->s_root); |
465 | 465 | /* |
466 | - * Use local name for "filesystems without rename() operation" | |
467 | - * or "path without vfsmount" or "absolute name is unavailable" | |
468 | - * cases. | |
466 | + * Use local name for "filesystems without rename() operation | |
467 | + * and device file" or "path without vfsmount" or "absolute | |
468 | + * name is unavailable" cases. | |
469 | 469 | */ |
470 | 470 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) |
471 | - if (!path->mnt || (inode->i_op && !inode->i_op->rename)) | |
471 | + if (!path->mnt || | |
472 | + (inode->i_op && !inode->i_op->rename && | |
473 | + !(sb->s_type->fs_flags & FS_REQUIRES_DEV))) | |
472 | 474 | pos = ERR_PTR(-EINVAL); |
473 | 475 | else { |
474 | 476 | /* Get absolute name for the rest. */ |
@@ -478,12 +480,15 @@ | ||
478 | 480 | } |
479 | 481 | #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) |
480 | 482 | if (!path->mnt || |
481 | - (!inode->i_op->rename && !inode->i_op->rename2)) | |
483 | + (!inode->i_op->rename && !inode->i_op->rename2 && | |
484 | + !(sb->s_type->fs_flags & FS_REQUIRES_DEV))) | |
482 | 485 | pos = ERR_PTR(-EINVAL); |
483 | 486 | else |
484 | 487 | pos = cs_get_absolute_path(path, buf, buf_len - 1); |
485 | 488 | #else |
486 | - if (!path->mnt || !inode->i_op->rename) | |
489 | + if (!path->mnt || | |
490 | + (!inode->i_op->rename && | |
491 | + !(sb->s_type->fs_flags & FS_REQUIRES_DEV))) | |
487 | 492 | pos = ERR_PTR(-EINVAL); |
488 | 493 | else |
489 | 494 | pos = cs_get_absolute_path(path, buf, buf_len - 1); |