diff options
Diffstat (limited to 'security')
| -rw-r--r-- | security/apparmor/lsm.c | 7 | ||||
| -rw-r--r-- | security/security.c | 10 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 379 | ||||
| -rw-r--r-- | security/selinux/include/classmap.h | 62 | ||||
| -rw-r--r-- | security/selinux/include/objsec.h | 10 | ||||
| -rw-r--r-- | security/selinux/include/security.h | 3 | ||||
| -rw-r--r-- | security/selinux/selinuxfs.c | 98 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 3 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 31 |
9 files changed, 327 insertions, 276 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index b63d39ca6278..709eacd23909 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
| @@ -505,8 +505,8 @@ static int apparmor_getprocattr(struct task_struct *task, char *name, | |||
| 505 | return error; | 505 | return error; |
| 506 | } | 506 | } |
| 507 | 507 | ||
| 508 | static int apparmor_setprocattr(struct task_struct *task, char *name, | 508 | static int apparmor_setprocattr(const char *name, void *value, |
| 509 | void *value, size_t size) | 509 | size_t size) |
| 510 | { | 510 | { |
| 511 | char *command, *largs = NULL, *args = value; | 511 | char *command, *largs = NULL, *args = value; |
| 512 | size_t arg_size; | 512 | size_t arg_size; |
| @@ -515,9 +515,6 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, | |||
| 515 | 515 | ||
| 516 | if (size == 0) | 516 | if (size == 0) |
| 517 | return -EINVAL; | 517 | return -EINVAL; |
| 518 | /* task can only write its own attributes */ | ||
| 519 | if (current != task) | ||
| 520 | return -EACCES; | ||
| 521 | 518 | ||
| 522 | /* AppArmor requires that the buffer must be null terminated atm */ | 519 | /* AppArmor requires that the buffer must be null terminated atm */ |
| 523 | if (args[size - 1] != '\0') { | 520 | if (args[size - 1] != '\0') { |
diff --git a/security/security.c b/security/security.c index f0a802ee29b6..d0e07f269b2d 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -1063,11 +1063,6 @@ int security_task_kill(struct task_struct *p, struct siginfo *info, | |||
| 1063 | return call_int_hook(task_kill, 0, p, info, sig, secid); | 1063 | return call_int_hook(task_kill, 0, p, info, sig, secid); |
| 1064 | } | 1064 | } |
| 1065 | 1065 | ||
| 1066 | int security_task_wait(struct task_struct *p) | ||
| 1067 | { | ||
| 1068 | return call_int_hook(task_wait, 0, p); | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, | 1066 | int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, |
| 1072 | unsigned long arg4, unsigned long arg5) | 1067 | unsigned long arg4, unsigned long arg5) |
| 1073 | { | 1068 | { |
| @@ -1208,9 +1203,9 @@ int security_getprocattr(struct task_struct *p, char *name, char **value) | |||
| 1208 | return call_int_hook(getprocattr, -EINVAL, p, name, value); | 1203 | return call_int_hook(getprocattr, -EINVAL, p, name, value); |
| 1209 | } | 1204 | } |
| 1210 | 1205 | ||
| 1211 | int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size) | 1206 | int security_setprocattr(const char *name, void *value, size_t size) |
| 1212 | { | 1207 | { |
| 1213 | return call_int_hook(setprocattr, -EINVAL, p, name, value, size); | 1208 | return call_int_hook(setprocattr, -EINVAL, name, value, size); |
| 1214 | } | 1209 | } |
| 1215 | 1210 | ||
| 1216 | int security_netlink_send(struct sock *sk, struct sk_buff *skb) | 1211 | int security_netlink_send(struct sock *sk, struct sk_buff *skb) |
| @@ -1807,7 +1802,6 @@ struct security_hook_heads security_hook_heads = { | |||
| 1807 | .task_movememory = | 1802 | .task_movememory = |
| 1808 | LIST_HEAD_INIT(security_hook_heads.task_movememory), | 1803 | LIST_HEAD_INIT(security_hook_heads.task_movememory), |
| 1809 | .task_kill = LIST_HEAD_INIT(security_hook_heads.task_kill), | 1804 | .task_kill = LIST_HEAD_INIT(security_hook_heads.task_kill), |
| 1810 | .task_wait = LIST_HEAD_INIT(security_hook_heads.task_wait), | ||
| 1811 | .task_prctl = LIST_HEAD_INIT(security_hook_heads.task_prctl), | 1805 | .task_prctl = LIST_HEAD_INIT(security_hook_heads.task_prctl), |
| 1812 | .task_to_inode = | 1806 | .task_to_inode = |
| 1813 | LIST_HEAD_INIT(security_hook_heads.task_to_inode), | 1807 | LIST_HEAD_INIT(security_hook_heads.task_to_inode), |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 424573029c5c..9bc12bcddc2c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -210,16 +210,6 @@ static inline u32 task_sid(const struct task_struct *task) | |||
| 210 | return sid; | 210 | return sid; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | /* | ||
| 214 | * get the subjective security ID of the current task | ||
| 215 | */ | ||
| 216 | static inline u32 current_sid(void) | ||
| 217 | { | ||
| 218 | const struct task_security_struct *tsec = current_security(); | ||
| 219 | |||
| 220 | return tsec->sid; | ||
| 221 | } | ||
| 222 | |||
| 223 | /* Allocate and free functions for each kind of security blob. */ | 213 | /* Allocate and free functions for each kind of security blob. */ |
| 224 | 214 | ||
| 225 | static int inode_alloc_security(struct inode *inode) | 215 | static int inode_alloc_security(struct inode *inode) |
| @@ -490,8 +480,11 @@ static int selinux_is_sblabel_mnt(struct super_block *sb) | |||
| 490 | sbsec->behavior == SECURITY_FS_USE_NATIVE || | 480 | sbsec->behavior == SECURITY_FS_USE_NATIVE || |
| 491 | /* Special handling. Genfs but also in-core setxattr handler */ | 481 | /* Special handling. Genfs but also in-core setxattr handler */ |
| 492 | !strcmp(sb->s_type->name, "sysfs") || | 482 | !strcmp(sb->s_type->name, "sysfs") || |
| 483 | !strcmp(sb->s_type->name, "cgroup") || | ||
| 484 | !strcmp(sb->s_type->name, "cgroup2") || | ||
| 493 | !strcmp(sb->s_type->name, "pstore") || | 485 | !strcmp(sb->s_type->name, "pstore") || |
| 494 | !strcmp(sb->s_type->name, "debugfs") || | 486 | !strcmp(sb->s_type->name, "debugfs") || |
| 487 | !strcmp(sb->s_type->name, "tracefs") || | ||
| 495 | !strcmp(sb->s_type->name, "rootfs"); | 488 | !strcmp(sb->s_type->name, "rootfs"); |
| 496 | } | 489 | } |
| 497 | 490 | ||
| @@ -833,10 +826,14 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
| 833 | } | 826 | } |
| 834 | 827 | ||
| 835 | /* | 828 | /* |
| 836 | * If this is a user namespace mount, no contexts are allowed | 829 | * If this is a user namespace mount and the filesystem type is not |
| 837 | * on the command line and security labels must be ignored. | 830 | * explicitly whitelisted, then no contexts are allowed on the command |
| 831 | * line and security labels must be ignored. | ||
| 838 | */ | 832 | */ |
| 839 | if (sb->s_user_ns != &init_user_ns) { | 833 | if (sb->s_user_ns != &init_user_ns && |
| 834 | strcmp(sb->s_type->name, "tmpfs") && | ||
| 835 | strcmp(sb->s_type->name, "ramfs") && | ||
| 836 | strcmp(sb->s_type->name, "devpts")) { | ||
| 840 | if (context_sid || fscontext_sid || rootcontext_sid || | 837 | if (context_sid || fscontext_sid || rootcontext_sid || |
| 841 | defcontext_sid) { | 838 | defcontext_sid) { |
| 842 | rc = -EACCES; | 839 | rc = -EACCES; |
| @@ -1268,6 +1265,8 @@ static inline int default_protocol_dgram(int protocol) | |||
| 1268 | 1265 | ||
| 1269 | static inline u16 socket_type_to_security_class(int family, int type, int protocol) | 1266 | static inline u16 socket_type_to_security_class(int family, int type, int protocol) |
| 1270 | { | 1267 | { |
| 1268 | int extsockclass = selinux_policycap_extsockclass; | ||
| 1269 | |||
| 1271 | switch (family) { | 1270 | switch (family) { |
| 1272 | case PF_UNIX: | 1271 | case PF_UNIX: |
| 1273 | switch (type) { | 1272 | switch (type) { |
| @@ -1282,13 +1281,19 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc | |||
| 1282 | case PF_INET6: | 1281 | case PF_INET6: |
| 1283 | switch (type) { | 1282 | switch (type) { |
| 1284 | case SOCK_STREAM: | 1283 | case SOCK_STREAM: |
| 1284 | case SOCK_SEQPACKET: | ||
| 1285 | if (default_protocol_stream(protocol)) | 1285 | if (default_protocol_stream(protocol)) |
| 1286 | return SECCLASS_TCP_SOCKET; | 1286 | return SECCLASS_TCP_SOCKET; |
| 1287 | else if (extsockclass && protocol == IPPROTO_SCTP) | ||
| 1288 | return SECCLASS_SCTP_SOCKET; | ||
| 1287 | else | 1289 | else |
| 1288 | return SECCLASS_RAWIP_SOCKET; | 1290 | return SECCLASS_RAWIP_SOCKET; |
| 1289 | case SOCK_DGRAM: | 1291 | case SOCK_DGRAM: |
| 1290 | if (default_protocol_dgram(protocol)) | 1292 | if (default_protocol_dgram(protocol)) |
| 1291 | return SECCLASS_UDP_SOCKET; | 1293 | return SECCLASS_UDP_SOCKET; |
| 1294 | else if (extsockclass && (protocol == IPPROTO_ICMP || | ||
| 1295 | protocol == IPPROTO_ICMPV6)) | ||
| 1296 | return SECCLASS_ICMP_SOCKET; | ||
| 1292 | else | 1297 | else |
| 1293 | return SECCLASS_RAWIP_SOCKET; | 1298 | return SECCLASS_RAWIP_SOCKET; |
| 1294 | case SOCK_DCCP: | 1299 | case SOCK_DCCP: |
| @@ -1342,6 +1347,66 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc | |||
| 1342 | return SECCLASS_APPLETALK_SOCKET; | 1347 | return SECCLASS_APPLETALK_SOCKET; |
| 1343 | } | 1348 | } |
| 1344 | 1349 | ||
| 1350 | if (extsockclass) { | ||
| 1351 | switch (family) { | ||
| 1352 | case PF_AX25: | ||
| 1353 | return SECCLASS_AX25_SOCKET; | ||
| 1354 | case PF_IPX: | ||
| 1355 | return SECCLASS_IPX_SOCKET; | ||
| 1356 | case PF_NETROM: | ||
| 1357 | return SECCLASS_NETROM_SOCKET; | ||
| 1358 | case PF_ATMPVC: | ||
| 1359 | return SECCLASS_ATMPVC_SOCKET; | ||
| 1360 | case PF_X25: | ||
| 1361 | return SECCLASS_X25_SOCKET; | ||
| 1362 | case PF_ROSE: | ||
| 1363 | return SECCLASS_ROSE_SOCKET; | ||
| 1364 | case PF_DECnet: | ||
| 1365 | return SECCLASS_DECNET_SOCKET; | ||
| 1366 | case PF_ATMSVC: | ||
| 1367 | return SECCLASS_ATMSVC_SOCKET; | ||
| 1368 | case PF_RDS: | ||
| 1369 | return SECCLASS_RDS_SOCKET; | ||
| 1370 | case PF_IRDA: | ||
| 1371 | return SECCLASS_IRDA_SOCKET; | ||
| 1372 | case PF_PPPOX: | ||
| 1373 | return SECCLASS_PPPOX_SOCKET; | ||
| 1374 | case PF_LLC: | ||
| 1375 | return SECCLASS_LLC_SOCKET; | ||
| 1376 | case PF_CAN: | ||
| 1377 | return SECCLASS_CAN_SOCKET; | ||
| 1378 | case PF_TIPC: | ||
| 1379 | return SECCLASS_TIPC_SOCKET; | ||
| 1380 | case PF_BLUETOOTH: | ||
| 1381 | return SECCLASS_BLUETOOTH_SOCKET; | ||
| 1382 | case PF_IUCV: | ||
| 1383 | return SECCLASS_IUCV_SOCKET; | ||
| 1384 | case PF_RXRPC: | ||
| 1385 | return SECCLASS_RXRPC_SOCKET; | ||
| 1386 | case PF_ISDN: | ||
| 1387 | return SECCLASS_ISDN_SOCKET; | ||
| 1388 | case PF_PHONET: | ||
| 1389 | return SECCLASS_PHONET_SOCKET; | ||
| 1390 | case PF_IEEE802154: | ||
| 1391 | return SECCLASS_IEEE802154_SOCKET; | ||
| 1392 | case PF_CAIF: | ||
| 1393 | return SECCLASS_CAIF_SOCKET; | ||
| 1394 | case PF_ALG: | ||
| 1395 | return SECCLASS_ALG_SOCKET; | ||
| 1396 | case PF_NFC: | ||
| 1397 | return SECCLASS_NFC_SOCKET; | ||
| 1398 | case PF_VSOCK: | ||
| 1399 | return SECCLASS_VSOCK_SOCKET; | ||
| 1400 | case PF_KCM: | ||
| 1401 | return SECCLASS_KCM_SOCKET; | ||
| 1402 | case PF_QIPCRTR: | ||
| 1403 | return SECCLASS_QIPCRTR_SOCKET; | ||
| 1404 | #if PF_MAX > 43 | ||
| 1405 | #error New address family defined, please update this function. | ||
| 1406 | #endif | ||
| 1407 | } | ||
| 1408 | } | ||
| 1409 | |||
| 1345 | return SECCLASS_SOCKET; | 1410 | return SECCLASS_SOCKET; |
| 1346 | } | 1411 | } |
| 1347 | 1412 | ||
| @@ -1608,55 +1673,6 @@ static inline u32 signal_to_av(int sig) | |||
| 1608 | return perm; | 1673 | return perm; |
| 1609 | } | 1674 | } |
| 1610 | 1675 | ||
| 1611 | /* | ||
| 1612 | * Check permission between a pair of credentials | ||
| 1613 | * fork check, ptrace check, etc. | ||
| 1614 | */ | ||
| 1615 | static int cred_has_perm(const struct cred *actor, | ||
| 1616 | const struct cred *target, | ||
| 1617 | u32 perms) | ||
| 1618 | { | ||
| 1619 | u32 asid = cred_sid(actor), tsid = cred_sid(target); | ||
| 1620 | |||
| 1621 | return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL); | ||
| 1622 | } | ||
| 1623 | |||
| 1624 | /* | ||
| 1625 | * Check permission between a pair of tasks, e.g. signal checks, | ||
| 1626 | * fork check, ptrace check, etc. | ||
| 1627 | * tsk1 is the actor and tsk2 is the target | ||
| 1628 | * - this uses the default subjective creds of tsk1 | ||
| 1629 | */ | ||
| 1630 | static int task_has_perm(const struct task_struct *tsk1, | ||
| 1631 | const struct task_struct *tsk2, | ||
| 1632 | u32 perms) | ||
| 1633 | { | ||
| 1634 | const struct task_security_struct *__tsec1, *__tsec2; | ||
| 1635 | u32 sid1, sid2; | ||
| 1636 | |||
| 1637 | rcu_read_lock(); | ||
| 1638 | __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid; | ||
| 1639 | __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid; | ||
| 1640 | rcu_read_unlock(); | ||
| 1641 | return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL); | ||
| 1642 | } | ||
| 1643 | |||
| 1644 | /* | ||
| 1645 | * Check permission between current and another task, e.g. signal checks, | ||
| 1646 | * fork check, ptrace check, etc. | ||
| 1647 | * current is the actor and tsk2 is the target | ||
| 1648 | * - this uses current's subjective creds | ||
| 1649 | */ | ||
| 1650 | static int current_has_perm(const struct task_struct *tsk, | ||
| 1651 | u32 perms) | ||
| 1652 | { | ||
| 1653 | u32 sid, tsid; | ||
| 1654 | |||
| 1655 | sid = current_sid(); | ||
| 1656 | tsid = task_sid(tsk); | ||
| 1657 | return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL); | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | #if CAP_LAST_CAP > 63 | 1676 | #if CAP_LAST_CAP > 63 |
| 1661 | #error Fix SELinux to handle capabilities > 63. | 1677 | #error Fix SELinux to handle capabilities > 63. |
| 1662 | #endif | 1678 | #endif |
| @@ -1698,16 +1714,6 @@ static int cred_has_capability(const struct cred *cred, | |||
| 1698 | return rc; | 1714 | return rc; |
| 1699 | } | 1715 | } |
| 1700 | 1716 | ||
| 1701 | /* Check whether a task is allowed to use a system operation. */ | ||
| 1702 | static int task_has_system(struct task_struct *tsk, | ||
| 1703 | u32 perms) | ||
| 1704 | { | ||
| 1705 | u32 sid = task_sid(tsk); | ||
| 1706 | |||
| 1707 | return avc_has_perm(sid, SECINITSID_KERNEL, | ||
| 1708 | SECCLASS_SYSTEM, perms, NULL); | ||
| 1709 | } | ||
| 1710 | |||
| 1711 | /* Check whether a task has a particular permission to an inode. | 1717 | /* Check whether a task has a particular permission to an inode. |
| 1712 | The 'adp' parameter is optional and allows other audit | 1718 | The 'adp' parameter is optional and allows other audit |
| 1713 | data to be passed (e.g. the dentry). */ | 1719 | data to be passed (e.g. the dentry). */ |
| @@ -1879,15 +1885,6 @@ static int may_create(struct inode *dir, | |||
| 1879 | FILESYSTEM__ASSOCIATE, &ad); | 1885 | FILESYSTEM__ASSOCIATE, &ad); |
| 1880 | } | 1886 | } |
| 1881 | 1887 | ||
| 1882 | /* Check whether a task can create a key. */ | ||
| 1883 | static int may_create_key(u32 ksid, | ||
| 1884 | struct task_struct *ctx) | ||
| 1885 | { | ||
| 1886 | u32 sid = task_sid(ctx); | ||
| 1887 | |||
| 1888 | return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL); | ||
| 1889 | } | ||
| 1890 | |||
| 1891 | #define MAY_LINK 0 | 1888 | #define MAY_LINK 0 |
| 1892 | #define MAY_UNLINK 1 | 1889 | #define MAY_UNLINK 1 |
| 1893 | #define MAY_RMDIR 2 | 1890 | #define MAY_RMDIR 2 |
| @@ -2143,24 +2140,26 @@ static int selinux_binder_transfer_file(struct task_struct *from, | |||
| 2143 | static int selinux_ptrace_access_check(struct task_struct *child, | 2140 | static int selinux_ptrace_access_check(struct task_struct *child, |
| 2144 | unsigned int mode) | 2141 | unsigned int mode) |
| 2145 | { | 2142 | { |
| 2146 | if (mode & PTRACE_MODE_READ) { | 2143 | u32 sid = current_sid(); |
| 2147 | u32 sid = current_sid(); | 2144 | u32 csid = task_sid(child); |
| 2148 | u32 csid = task_sid(child); | 2145 | |
| 2146 | if (mode & PTRACE_MODE_READ) | ||
| 2149 | return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); | 2147 | return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); |
| 2150 | } | ||
| 2151 | 2148 | ||
| 2152 | return current_has_perm(child, PROCESS__PTRACE); | 2149 | return avc_has_perm(sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); |
| 2153 | } | 2150 | } |
| 2154 | 2151 | ||
| 2155 | static int selinux_ptrace_traceme(struct task_struct *parent) | 2152 | static int selinux_ptrace_traceme(struct task_struct *parent) |
| 2156 | { | 2153 | { |
| 2157 | return task_has_perm(parent, current, PROCESS__PTRACE); | 2154 | return avc_has_perm(task_sid(parent), current_sid(), SECCLASS_PROCESS, |
| 2155 | PROCESS__PTRACE, NULL); | ||
| 2158 | } | 2156 | } |
| 2159 | 2157 | ||
| 2160 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, | 2158 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, |
| 2161 | kernel_cap_t *inheritable, kernel_cap_t *permitted) | 2159 | kernel_cap_t *inheritable, kernel_cap_t *permitted) |
| 2162 | { | 2160 | { |
| 2163 | return current_has_perm(target, PROCESS__GETCAP); | 2161 | return avc_has_perm(current_sid(), task_sid(target), SECCLASS_PROCESS, |
| 2162 | PROCESS__GETCAP, NULL); | ||
| 2164 | } | 2163 | } |
| 2165 | 2164 | ||
| 2166 | static int selinux_capset(struct cred *new, const struct cred *old, | 2165 | static int selinux_capset(struct cred *new, const struct cred *old, |
| @@ -2168,7 +2167,8 @@ static int selinux_capset(struct cred *new, const struct cred *old, | |||
| 2168 | const kernel_cap_t *inheritable, | 2167 | const kernel_cap_t *inheritable, |
| 2169 | const kernel_cap_t *permitted) | 2168 | const kernel_cap_t *permitted) |
| 2170 | { | 2169 | { |
| 2171 | return cred_has_perm(old, new, PROCESS__SETCAP); | 2170 | return avc_has_perm(cred_sid(old), cred_sid(new), SECCLASS_PROCESS, |
| 2171 | PROCESS__SETCAP, NULL); | ||
| 2172 | } | 2172 | } |
| 2173 | 2173 | ||
| 2174 | /* | 2174 | /* |
| @@ -2224,29 +2224,22 @@ static int selinux_quota_on(struct dentry *dentry) | |||
| 2224 | 2224 | ||
| 2225 | static int selinux_syslog(int type) | 2225 | static int selinux_syslog(int type) |
| 2226 | { | 2226 | { |
| 2227 | int rc; | ||
| 2228 | |||
| 2229 | switch (type) { | 2227 | switch (type) { |
| 2230 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ | 2228 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ |
| 2231 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ | 2229 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ |
| 2232 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); | 2230 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, |
| 2233 | break; | 2231 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL); |
| 2234 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ | 2232 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ |
| 2235 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ | 2233 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ |
| 2236 | /* Set level of messages printed to console */ | 2234 | /* Set level of messages printed to console */ |
| 2237 | case SYSLOG_ACTION_CONSOLE_LEVEL: | 2235 | case SYSLOG_ACTION_CONSOLE_LEVEL: |
| 2238 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); | 2236 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, |
| 2239 | break; | 2237 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, |
| 2240 | case SYSLOG_ACTION_CLOSE: /* Close log */ | 2238 | NULL); |
| 2241 | case SYSLOG_ACTION_OPEN: /* Open log */ | ||
| 2242 | case SYSLOG_ACTION_READ: /* Read from log */ | ||
| 2243 | case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */ | ||
| 2244 | case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */ | ||
| 2245 | default: | ||
| 2246 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); | ||
| 2247 | break; | ||
| 2248 | } | 2239 | } |
| 2249 | return rc; | 2240 | /* All other syslog types */ |
| 2241 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, | ||
| 2242 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL); | ||
| 2250 | } | 2243 | } |
| 2251 | 2244 | ||
| 2252 | /* | 2245 | /* |
| @@ -2271,13 +2264,13 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | |||
| 2271 | 2264 | ||
| 2272 | /* binprm security operations */ | 2265 | /* binprm security operations */ |
| 2273 | 2266 | ||
| 2274 | static u32 ptrace_parent_sid(struct task_struct *task) | 2267 | static u32 ptrace_parent_sid(void) |
| 2275 | { | 2268 | { |
| 2276 | u32 sid = 0; | 2269 | u32 sid = 0; |
| 2277 | struct task_struct *tracer; | 2270 | struct task_struct *tracer; |
| 2278 | 2271 | ||
| 2279 | rcu_read_lock(); | 2272 | rcu_read_lock(); |
| 2280 | tracer = ptrace_parent(task); | 2273 | tracer = ptrace_parent(current); |
| 2281 | if (tracer) | 2274 | if (tracer) |
| 2282 | sid = task_sid(tracer); | 2275 | sid = task_sid(tracer); |
| 2283 | rcu_read_unlock(); | 2276 | rcu_read_unlock(); |
| @@ -2406,7 +2399,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
| 2406 | * changes its SID has the appropriate permit */ | 2399 | * changes its SID has the appropriate permit */ |
| 2407 | if (bprm->unsafe & | 2400 | if (bprm->unsafe & |
| 2408 | (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { | 2401 | (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { |
| 2409 | u32 ptsid = ptrace_parent_sid(current); | 2402 | u32 ptsid = ptrace_parent_sid(); |
| 2410 | if (ptsid != 0) { | 2403 | if (ptsid != 0) { |
| 2411 | rc = avc_has_perm(ptsid, new_tsec->sid, | 2404 | rc = avc_has_perm(ptsid, new_tsec->sid, |
| 2412 | SECCLASS_PROCESS, | 2405 | SECCLASS_PROCESS, |
| @@ -3503,6 +3496,7 @@ static int default_noexec; | |||
| 3503 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 3496 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
| 3504 | { | 3497 | { |
| 3505 | const struct cred *cred = current_cred(); | 3498 | const struct cred *cred = current_cred(); |
| 3499 | u32 sid = cred_sid(cred); | ||
| 3506 | int rc = 0; | 3500 | int rc = 0; |
| 3507 | 3501 | ||
| 3508 | if (default_noexec && | 3502 | if (default_noexec && |
| @@ -3513,7 +3507,8 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
| 3513 | * private file mapping that will also be writable. | 3507 | * private file mapping that will also be writable. |
| 3514 | * This has an additional check. | 3508 | * This has an additional check. |
| 3515 | */ | 3509 | */ |
| 3516 | rc = cred_has_perm(cred, cred, PROCESS__EXECMEM); | 3510 | rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, |
| 3511 | PROCESS__EXECMEM, NULL); | ||
| 3517 | if (rc) | 3512 | if (rc) |
| 3518 | goto error; | 3513 | goto error; |
| 3519 | } | 3514 | } |
| @@ -3564,6 +3559,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
| 3564 | unsigned long prot) | 3559 | unsigned long prot) |
| 3565 | { | 3560 | { |
| 3566 | const struct cred *cred = current_cred(); | 3561 | const struct cred *cred = current_cred(); |
| 3562 | u32 sid = cred_sid(cred); | ||
| 3567 | 3563 | ||
| 3568 | if (selinux_checkreqprot) | 3564 | if (selinux_checkreqprot) |
| 3569 | prot = reqprot; | 3565 | prot = reqprot; |
| @@ -3573,12 +3569,14 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
| 3573 | int rc = 0; | 3569 | int rc = 0; |
| 3574 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3570 | if (vma->vm_start >= vma->vm_mm->start_brk && |
| 3575 | vma->vm_end <= vma->vm_mm->brk) { | 3571 | vma->vm_end <= vma->vm_mm->brk) { |
| 3576 | rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); | 3572 | rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, |
| 3573 | PROCESS__EXECHEAP, NULL); | ||
| 3577 | } else if (!vma->vm_file && | 3574 | } else if (!vma->vm_file && |
| 3578 | ((vma->vm_start <= vma->vm_mm->start_stack && | 3575 | ((vma->vm_start <= vma->vm_mm->start_stack && |
| 3579 | vma->vm_end >= vma->vm_mm->start_stack) || | 3576 | vma->vm_end >= vma->vm_mm->start_stack) || |
| 3580 | vma_is_stack_for_current(vma))) { | 3577 | vma_is_stack_for_current(vma))) { |
| 3581 | rc = current_has_perm(current, PROCESS__EXECSTACK); | 3578 | rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, |
| 3579 | PROCESS__EXECSTACK, NULL); | ||
| 3582 | } else if (vma->vm_file && vma->anon_vma) { | 3580 | } else if (vma->vm_file && vma->anon_vma) { |
| 3583 | /* | 3581 | /* |
| 3584 | * We are making executable a file mapping that has | 3582 | * We are making executable a file mapping that has |
| @@ -3711,7 +3709,9 @@ static int selinux_file_open(struct file *file, const struct cred *cred) | |||
| 3711 | 3709 | ||
| 3712 | static int selinux_task_create(unsigned long clone_flags) | 3710 | static int selinux_task_create(unsigned long clone_flags) |
| 3713 | { | 3711 | { |
| 3714 | return current_has_perm(current, PROCESS__FORK); | 3712 | u32 sid = current_sid(); |
| 3713 | |||
| 3714 | return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL); | ||
| 3715 | } | 3715 | } |
| 3716 | 3716 | ||
| 3717 | /* | 3717 | /* |
| @@ -3821,15 +3821,12 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
| 3821 | 3821 | ||
| 3822 | static int selinux_kernel_module_request(char *kmod_name) | 3822 | static int selinux_kernel_module_request(char *kmod_name) |
| 3823 | { | 3823 | { |
| 3824 | u32 sid; | ||
| 3825 | struct common_audit_data ad; | 3824 | struct common_audit_data ad; |
| 3826 | 3825 | ||
| 3827 | sid = task_sid(current); | ||
| 3828 | |||
| 3829 | ad.type = LSM_AUDIT_DATA_KMOD; | 3826 | ad.type = LSM_AUDIT_DATA_KMOD; |
| 3830 | ad.u.kmod_name = kmod_name; | 3827 | ad.u.kmod_name = kmod_name; |
| 3831 | 3828 | ||
| 3832 | return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, | 3829 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, |
| 3833 | SYSTEM__MODULE_REQUEST, &ad); | 3830 | SYSTEM__MODULE_REQUEST, &ad); |
| 3834 | } | 3831 | } |
| 3835 | 3832 | ||
| @@ -3881,17 +3878,20 @@ static int selinux_kernel_read_file(struct file *file, | |||
| 3881 | 3878 | ||
| 3882 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3879 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
| 3883 | { | 3880 | { |
| 3884 | return current_has_perm(p, PROCESS__SETPGID); | 3881 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
| 3882 | PROCESS__SETPGID, NULL); | ||
| 3885 | } | 3883 | } |
| 3886 | 3884 | ||
| 3887 | static int selinux_task_getpgid(struct task_struct *p) | 3885 | static int selinux_task_getpgid(struct task_struct *p) |
| 3888 | { | 3886 | { |
| 3889 | return current_has_perm(p, PROCESS__GETPGID); | 3887 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
| 3888 | PROCESS__GETPGID, NULL); | ||
| 3890 | } | 3889 | } |
| 3891 | 3890 | ||
| 3892 | static int selinux_task_getsid(struct task_struct *p) | 3891 | static int selinux_task_getsid(struct task_struct *p) |
| 3893 | { | 3892 | { |
| 3894 | return current_has_perm(p, PROCESS__GETSESSION); | 3893 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
| 3894 | PROCESS__GETSESSION, NULL); | ||
| 3895 | } | 3895 | } |
| 3896 | 3896 | ||
| 3897 | static void selinux_task_getsecid(struct task_struct *p, u32 *secid) | 3897 | static void selinux_task_getsecid(struct task_struct *p, u32 *secid) |
| @@ -3901,17 +3901,20 @@ static void selinux_task_getsecid(struct task_struct *p, u32 *secid) | |||
| 3901 | 3901 | ||
| 3902 | static int selinux_task_setnice(struct task_struct *p, int nice) | 3902 | static int selinux_task_setnice(struct task_struct *p, int nice) |
| 3903 | { | 3903 | { |
| 3904 | return current_has_perm(p, PROCESS__SETSCHED); | 3904 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
| 3905 | PROCESS__SETSCHED, NULL); | ||
| 3905 | } | 3906 | } |
| 3906 | 3907 | ||
| 3907 | static int selinux_task_setioprio(struct task_struct *p, int ioprio) | 3908 | static int selinux_task_setioprio(struct task_struct *p, int ioprio) |
| 3908 | { | 3909 | { |
| 3909 | return current_has_perm(p, PROCESS__SETSCHED); | 3910 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
| 3911 | PROCESS__SETSCHED, NULL); | ||
| 3910 | } | 3912 | } |
| 3911 | 3913 | ||
| 3912 | static int selinux_task_getioprio(struct task_struct *p) | 3914 | static int selinux_task_getioprio(struct task_struct *p) |
| 3913 | { | 3915 | { |
| 3914 | return current_has_perm(p, PROCESS__GETSCHED); | 3916 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
| 3917 | PROCESS__GETSCHED, NULL); | ||
| 3915 | } | 3918 | } |
| 3916 | 3919 | ||
| 3917 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, | 3920 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, |
| @@ -3924,47 +3927,42 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, | |||
| 3924 | later be used as a safe reset point for the soft limit | 3927 | later be used as a safe reset point for the soft limit |
| 3925 | upon context transitions. See selinux_bprm_committing_creds. */ | 3928 | upon context transitions. See selinux_bprm_committing_creds. */ |
| 3926 | if (old_rlim->rlim_max != new_rlim->rlim_max) | 3929 | if (old_rlim->rlim_max != new_rlim->rlim_max) |
| 3927 | return current_has_perm(p, PROCESS__SETRLIMIT); | 3930 | return avc_has_perm(current_sid(), task_sid(p), |
| 3931 | SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL); | ||
| 3928 | 3932 | ||
| 3929 | return 0; | 3933 | return 0; |
| 3930 | } | 3934 | } |
| 3931 | 3935 | ||
| 3932 | static int selinux_task_setscheduler(struct task_struct *p) | 3936 | static int selinux_task_setscheduler(struct task_struct *p) |
| 3933 | { | 3937 | { |
| 3934 | return current_has_perm(p, PROCESS__SETSCHED); | 3938 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
| 3939 | PROCESS__SETSCHED, NULL); | ||
| 3935 | } | 3940 | } |
| 3936 | 3941 | ||
| 3937 | static int selinux_task_getscheduler(struct task_struct *p) | 3942 | static int selinux_task_getscheduler(struct task_struct *p) |
| 3938 | { | 3943 | { |
| 3939 | return current_has_perm(p, PROCESS__GETSCHED); | 3944 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
| 3945 | PROCESS__GETSCHED, NULL); | ||
| 3940 | } | 3946 | } |
| 3941 | 3947 | ||
| 3942 | static int selinux_task_movememory(struct task_struct *p) | 3948 | static int selinux_task_movememory(struct task_struct *p) |
| 3943 | { | 3949 | { |
| 3944 | return current_has_perm(p, PROCESS__SETSCHED); | 3950 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
| 3951 | PROCESS__SETSCHED, NULL); | ||
| 3945 | } | 3952 | } |
| 3946 | 3953 | ||
| 3947 | static int selinux_task_kill(struct task_struct *p, struct siginfo *info, | 3954 | static int selinux_task_kill(struct task_struct *p, struct siginfo *info, |
| 3948 | int sig, u32 secid) | 3955 | int sig, u32 secid) |
| 3949 | { | 3956 | { |
| 3950 | u32 perm; | 3957 | u32 perm; |
| 3951 | int rc; | ||
| 3952 | 3958 | ||
| 3953 | if (!sig) | 3959 | if (!sig) |
| 3954 | perm = PROCESS__SIGNULL; /* null signal; existence test */ | 3960 | perm = PROCESS__SIGNULL; /* null signal; existence test */ |
| 3955 | else | 3961 | else |
| 3956 | perm = signal_to_av(sig); | 3962 | perm = signal_to_av(sig); |
| 3957 | if (secid) | 3963 | if (!secid) |
| 3958 | rc = avc_has_perm(secid, task_sid(p), | 3964 | secid = current_sid(); |
| 3959 | SECCLASS_PROCESS, perm, NULL); | 3965 | return avc_has_perm(secid, task_sid(p), SECCLASS_PROCESS, perm, NULL); |
| 3960 | else | ||
| 3961 | rc = current_has_perm(p, perm); | ||
| 3962 | return rc; | ||
| 3963 | } | ||
| 3964 | |||
| 3965 | static int selinux_task_wait(struct task_struct *p) | ||
| 3966 | { | ||
| 3967 | return task_has_perm(p, current, PROCESS__SIGCHLD); | ||
| 3968 | } | 3966 | } |
| 3969 | 3967 | ||
| 3970 | static void selinux_task_to_inode(struct task_struct *p, | 3968 | static void selinux_task_to_inode(struct task_struct *p, |
| @@ -4254,12 +4252,11 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec, | |||
| 4254 | socksid); | 4252 | socksid); |
| 4255 | } | 4253 | } |
| 4256 | 4254 | ||
| 4257 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) | 4255 | static int sock_has_perm(struct sock *sk, u32 perms) |
| 4258 | { | 4256 | { |
| 4259 | struct sk_security_struct *sksec = sk->sk_security; | 4257 | struct sk_security_struct *sksec = sk->sk_security; |
| 4260 | struct common_audit_data ad; | 4258 | struct common_audit_data ad; |
| 4261 | struct lsm_network_audit net = {0,}; | 4259 | struct lsm_network_audit net = {0,}; |
| 4262 | u32 tsid = task_sid(task); | ||
| 4263 | 4260 | ||
| 4264 | if (sksec->sid == SECINITSID_KERNEL) | 4261 | if (sksec->sid == SECINITSID_KERNEL) |
| 4265 | return 0; | 4262 | return 0; |
| @@ -4268,7 +4265,8 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) | |||
| 4268 | ad.u.net = &net; | 4265 | ad.u.net = &net; |
| 4269 | ad.u.net->sk = sk; | 4266 | ad.u.net->sk = sk; |
| 4270 | 4267 | ||
| 4271 | return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); | 4268 | return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms, |
| 4269 | &ad); | ||
| 4272 | } | 4270 | } |
| 4273 | 4271 | ||
| 4274 | static int selinux_socket_create(int family, int type, | 4272 | static int selinux_socket_create(int family, int type, |
| @@ -4330,7 +4328,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 4330 | u16 family; | 4328 | u16 family; |
| 4331 | int err; | 4329 | int err; |
| 4332 | 4330 | ||
| 4333 | err = sock_has_perm(current, sk, SOCKET__BIND); | 4331 | err = sock_has_perm(sk, SOCKET__BIND); |
| 4334 | if (err) | 4332 | if (err) |
| 4335 | goto out; | 4333 | goto out; |
| 4336 | 4334 | ||
| @@ -4429,7 +4427,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
| 4429 | struct sk_security_struct *sksec = sk->sk_security; | 4427 | struct sk_security_struct *sksec = sk->sk_security; |
| 4430 | int err; | 4428 | int err; |
| 4431 | 4429 | ||
| 4432 | err = sock_has_perm(current, sk, SOCKET__CONNECT); | 4430 | err = sock_has_perm(sk, SOCKET__CONNECT); |
| 4433 | if (err) | 4431 | if (err) |
| 4434 | return err; | 4432 | return err; |
| 4435 | 4433 | ||
| @@ -4481,7 +4479,7 @@ out: | |||
| 4481 | 4479 | ||
| 4482 | static int selinux_socket_listen(struct socket *sock, int backlog) | 4480 | static int selinux_socket_listen(struct socket *sock, int backlog) |
| 4483 | { | 4481 | { |
| 4484 | return sock_has_perm(current, sock->sk, SOCKET__LISTEN); | 4482 | return sock_has_perm(sock->sk, SOCKET__LISTEN); |
| 4485 | } | 4483 | } |
| 4486 | 4484 | ||
| 4487 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | 4485 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) |
| @@ -4492,7 +4490,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
| 4492 | u16 sclass; | 4490 | u16 sclass; |
| 4493 | u32 sid; | 4491 | u32 sid; |
| 4494 | 4492 | ||
| 4495 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); | 4493 | err = sock_has_perm(sock->sk, SOCKET__ACCEPT); |
| 4496 | if (err) | 4494 | if (err) |
| 4497 | return err; | 4495 | return err; |
| 4498 | 4496 | ||
| @@ -4513,30 +4511,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
| 4513 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 4511 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
| 4514 | int size) | 4512 | int size) |
| 4515 | { | 4513 | { |
| 4516 | return sock_has_perm(current, sock->sk, SOCKET__WRITE); | 4514 | return sock_has_perm(sock->sk, SOCKET__WRITE); |
| 4517 | } | 4515 | } |
| 4518 | 4516 | ||
| 4519 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 4517 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
| 4520 | int size, int flags) | 4518 | int size, int flags) |
| 4521 | { | 4519 | { |
| 4522 | return sock_has_perm(current, sock->sk, SOCKET__READ); | 4520 | return sock_has_perm(sock->sk, SOCKET__READ); |
| 4523 | } | 4521 | } |
| 4524 | 4522 | ||
| 4525 | static int selinux_socket_getsockname(struct socket *sock) | 4523 | static int selinux_socket_getsockname(struct socket *sock) |
| 4526 | { | 4524 | { |
| 4527 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); | 4525 | return sock_has_perm(sock->sk, SOCKET__GETATTR); |
| 4528 | } | 4526 | } |
| 4529 | 4527 | ||
| 4530 | static int selinux_socket_getpeername(struct socket *sock) | 4528 | static int selinux_socket_getpeername(struct socket *sock) |
| 4531 | { | 4529 | { |
| 4532 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); | 4530 | return sock_has_perm(sock->sk, SOCKET__GETATTR); |
| 4533 | } | 4531 | } |
| 4534 | 4532 | ||
| 4535 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) | 4533 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) |
| 4536 | { | 4534 | { |
| 4537 | int err; | 4535 | int err; |
| 4538 | 4536 | ||
| 4539 | err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); | 4537 | err = sock_has_perm(sock->sk, SOCKET__SETOPT); |
| 4540 | if (err) | 4538 | if (err) |
| 4541 | return err; | 4539 | return err; |
| 4542 | 4540 | ||
| @@ -4546,12 +4544,12 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname | |||
| 4546 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 4544 | static int selinux_socket_getsockopt(struct socket *sock, int level, |
| 4547 | int optname) | 4545 | int optname) |
| 4548 | { | 4546 | { |
| 4549 | return sock_has_perm(current, sock->sk, SOCKET__GETOPT); | 4547 | return sock_has_perm(sock->sk, SOCKET__GETOPT); |
| 4550 | } | 4548 | } |
| 4551 | 4549 | ||
| 4552 | static int selinux_socket_shutdown(struct socket *sock, int how) | 4550 | static int selinux_socket_shutdown(struct socket *sock, int how) |
| 4553 | { | 4551 | { |
| 4554 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); | 4552 | return sock_has_perm(sock->sk, SOCKET__SHUTDOWN); |
| 4555 | } | 4553 | } |
| 4556 | 4554 | ||
| 4557 | static int selinux_socket_unix_stream_connect(struct sock *sock, | 4555 | static int selinux_socket_unix_stream_connect(struct sock *sock, |
| @@ -5039,7 +5037,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
| 5039 | goto out; | 5037 | goto out; |
| 5040 | } | 5038 | } |
| 5041 | 5039 | ||
| 5042 | err = sock_has_perm(current, sk, perm); | 5040 | err = sock_has_perm(sk, perm); |
| 5043 | out: | 5041 | out: |
| 5044 | return err; | 5042 | return err; |
| 5045 | } | 5043 | } |
| @@ -5370,20 +5368,17 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
| 5370 | return selinux_nlmsg_perm(sk, skb); | 5368 | return selinux_nlmsg_perm(sk, skb); |
| 5371 | } | 5369 | } |
| 5372 | 5370 | ||
| 5373 | static int ipc_alloc_security(struct task_struct *task, | 5371 | static int ipc_alloc_security(struct kern_ipc_perm *perm, |
| 5374 | struct kern_ipc_perm *perm, | ||
| 5375 | u16 sclass) | 5372 | u16 sclass) |
| 5376 | { | 5373 | { |
| 5377 | struct ipc_security_struct *isec; | 5374 | struct ipc_security_struct *isec; |
| 5378 | u32 sid; | ||
| 5379 | 5375 | ||
| 5380 | isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); | 5376 | isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); |
| 5381 | if (!isec) | 5377 | if (!isec) |
| 5382 | return -ENOMEM; | 5378 | return -ENOMEM; |
| 5383 | 5379 | ||
| 5384 | sid = task_sid(task); | ||
| 5385 | isec->sclass = sclass; | 5380 | isec->sclass = sclass; |
| 5386 | isec->sid = sid; | 5381 | isec->sid = current_sid(); |
| 5387 | perm->security = isec; | 5382 | perm->security = isec; |
| 5388 | 5383 | ||
| 5389 | return 0; | 5384 | return 0; |
| @@ -5451,7 +5446,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
| 5451 | u32 sid = current_sid(); | 5446 | u32 sid = current_sid(); |
| 5452 | int rc; | 5447 | int rc; |
| 5453 | 5448 | ||
| 5454 | rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ); | 5449 | rc = ipc_alloc_security(&msq->q_perm, SECCLASS_MSGQ); |
| 5455 | if (rc) | 5450 | if (rc) |
| 5456 | return rc; | 5451 | return rc; |
| 5457 | 5452 | ||
| @@ -5498,7 +5493,8 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd) | |||
| 5498 | case IPC_INFO: | 5493 | case IPC_INFO: |
| 5499 | case MSG_INFO: | 5494 | case MSG_INFO: |
| 5500 | /* No specific object, just general system-wide information. */ | 5495 | /* No specific object, just general system-wide information. */ |
| 5501 | return task_has_system(current, SYSTEM__IPC_INFO); | 5496 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, |
| 5497 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); | ||
| 5502 | case IPC_STAT: | 5498 | case IPC_STAT: |
| 5503 | case MSG_STAT: | 5499 | case MSG_STAT: |
| 5504 | perms = MSGQ__GETATTR | MSGQ__ASSOCIATE; | 5500 | perms = MSGQ__GETATTR | MSGQ__ASSOCIATE; |
| @@ -5592,7 +5588,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
| 5592 | u32 sid = current_sid(); | 5588 | u32 sid = current_sid(); |
| 5593 | int rc; | 5589 | int rc; |
| 5594 | 5590 | ||
| 5595 | rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM); | 5591 | rc = ipc_alloc_security(&shp->shm_perm, SECCLASS_SHM); |
| 5596 | if (rc) | 5592 | if (rc) |
| 5597 | return rc; | 5593 | return rc; |
| 5598 | 5594 | ||
| @@ -5640,7 +5636,8 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd) | |||
| 5640 | case IPC_INFO: | 5636 | case IPC_INFO: |
| 5641 | case SHM_INFO: | 5637 | case SHM_INFO: |
| 5642 | /* No specific object, just general system-wide information. */ | 5638 | /* No specific object, just general system-wide information. */ |
| 5643 | return task_has_system(current, SYSTEM__IPC_INFO); | 5639 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, |
| 5640 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); | ||
| 5644 | case IPC_STAT: | 5641 | case IPC_STAT: |
| 5645 | case SHM_STAT: | 5642 | case SHM_STAT: |
| 5646 | perms = SHM__GETATTR | SHM__ASSOCIATE; | 5643 | perms = SHM__GETATTR | SHM__ASSOCIATE; |
| @@ -5684,7 +5681,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
| 5684 | u32 sid = current_sid(); | 5681 | u32 sid = current_sid(); |
| 5685 | int rc; | 5682 | int rc; |
| 5686 | 5683 | ||
| 5687 | rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM); | 5684 | rc = ipc_alloc_security(&sma->sem_perm, SECCLASS_SEM); |
| 5688 | if (rc) | 5685 | if (rc) |
| 5689 | return rc; | 5686 | return rc; |
| 5690 | 5687 | ||
| @@ -5732,7 +5729,8 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd) | |||
| 5732 | case IPC_INFO: | 5729 | case IPC_INFO: |
| 5733 | case SEM_INFO: | 5730 | case SEM_INFO: |
| 5734 | /* No specific object, just general system-wide information. */ | 5731 | /* No specific object, just general system-wide information. */ |
| 5735 | return task_has_system(current, SYSTEM__IPC_INFO); | 5732 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, |
| 5733 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); | ||
| 5736 | case GETPID: | 5734 | case GETPID: |
| 5737 | case GETNCNT: | 5735 | case GETNCNT: |
| 5738 | case GETZCNT: | 5736 | case GETZCNT: |
| @@ -5813,15 +5811,16 @@ static int selinux_getprocattr(struct task_struct *p, | |||
| 5813 | int error; | 5811 | int error; |
| 5814 | unsigned len; | 5812 | unsigned len; |
| 5815 | 5813 | ||
| 5814 | rcu_read_lock(); | ||
| 5815 | __tsec = __task_cred(p)->security; | ||
| 5816 | |||
| 5816 | if (current != p) { | 5817 | if (current != p) { |
| 5817 | error = current_has_perm(p, PROCESS__GETATTR); | 5818 | error = avc_has_perm(current_sid(), __tsec->sid, |
| 5819 | SECCLASS_PROCESS, PROCESS__GETATTR, NULL); | ||
| 5818 | if (error) | 5820 | if (error) |
| 5819 | return error; | 5821 | goto bad; |
| 5820 | } | 5822 | } |
| 5821 | 5823 | ||
| 5822 | rcu_read_lock(); | ||
| 5823 | __tsec = __task_cred(p)->security; | ||
| 5824 | |||
| 5825 | if (!strcmp(name, "current")) | 5824 | if (!strcmp(name, "current")) |
| 5826 | sid = __tsec->sid; | 5825 | sid = __tsec->sid; |
| 5827 | else if (!strcmp(name, "prev")) | 5826 | else if (!strcmp(name, "prev")) |
| @@ -5834,8 +5833,10 @@ static int selinux_getprocattr(struct task_struct *p, | |||
| 5834 | sid = __tsec->keycreate_sid; | 5833 | sid = __tsec->keycreate_sid; |
| 5835 | else if (!strcmp(name, "sockcreate")) | 5834 | else if (!strcmp(name, "sockcreate")) |
| 5836 | sid = __tsec->sockcreate_sid; | 5835 | sid = __tsec->sockcreate_sid; |
| 5837 | else | 5836 | else { |
| 5838 | goto invalid; | 5837 | error = -EINVAL; |
| 5838 | goto bad; | ||
| 5839 | } | ||
| 5839 | rcu_read_unlock(); | 5840 | rcu_read_unlock(); |
| 5840 | 5841 | ||
| 5841 | if (!sid) | 5842 | if (!sid) |
| @@ -5846,41 +5847,37 @@ static int selinux_getprocattr(struct task_struct *p, | |||
| 5846 | return error; | 5847 | return error; |
| 5847 | return len; | 5848 | return len; |
| 5848 | 5849 | ||
| 5849 | invalid: | 5850 | bad: |
| 5850 | rcu_read_unlock(); | 5851 | rcu_read_unlock(); |
| 5851 | return -EINVAL; | 5852 | return error; |
| 5852 | } | 5853 | } |
| 5853 | 5854 | ||
| 5854 | static int selinux_setprocattr(struct task_struct *p, | 5855 | static int selinux_setprocattr(const char *name, void *value, size_t size) |
| 5855 | char *name, void *value, size_t size) | ||
| 5856 | { | 5856 | { |
| 5857 | struct task_security_struct *tsec; | 5857 | struct task_security_struct *tsec; |
| 5858 | struct cred *new; | 5858 | struct cred *new; |
| 5859 | u32 sid = 0, ptsid; | 5859 | u32 mysid = current_sid(), sid = 0, ptsid; |
| 5860 | int error; | 5860 | int error; |
| 5861 | char *str = value; | 5861 | char *str = value; |
| 5862 | 5862 | ||
| 5863 | if (current != p) { | ||
| 5864 | /* SELinux only allows a process to change its own | ||
| 5865 | security attributes. */ | ||
| 5866 | return -EACCES; | ||
| 5867 | } | ||
| 5868 | |||
| 5869 | /* | 5863 | /* |
| 5870 | * Basic control over ability to set these attributes at all. | 5864 | * Basic control over ability to set these attributes at all. |
| 5871 | * current == p, but we'll pass them separately in case the | ||
| 5872 | * above restriction is ever removed. | ||
| 5873 | */ | 5865 | */ |
| 5874 | if (!strcmp(name, "exec")) | 5866 | if (!strcmp(name, "exec")) |
| 5875 | error = current_has_perm(p, PROCESS__SETEXEC); | 5867 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, |
| 5868 | PROCESS__SETEXEC, NULL); | ||
| 5876 | else if (!strcmp(name, "fscreate")) | 5869 | else if (!strcmp(name, "fscreate")) |
| 5877 | error = current_has_perm(p, PROCESS__SETFSCREATE); | 5870 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, |
| 5871 | PROCESS__SETFSCREATE, NULL); | ||
| 5878 | else if (!strcmp(name, "keycreate")) | 5872 | else if (!strcmp(name, "keycreate")) |
| 5879 | error = current_has_perm(p, PROCESS__SETKEYCREATE); | 5873 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, |
| 5874 | PROCESS__SETKEYCREATE, NULL); | ||
| 5880 | else if (!strcmp(name, "sockcreate")) | 5875 | else if (!strcmp(name, "sockcreate")) |
| 5881 | error = current_has_perm(p, PROCESS__SETSOCKCREATE); | 5876 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, |
| 5877 | PROCESS__SETSOCKCREATE, NULL); | ||
| 5882 | else if (!strcmp(name, "current")) | 5878 | else if (!strcmp(name, "current")) |
| 5883 | error = current_has_perm(p, PROCESS__SETCURRENT); | 5879 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, |
| 5880 | PROCESS__SETCURRENT, NULL); | ||
| 5884 | else | 5881 | else |
| 5885 | error = -EINVAL; | 5882 | error = -EINVAL; |
| 5886 | if (error) | 5883 | if (error) |
| @@ -5934,7 +5931,8 @@ static int selinux_setprocattr(struct task_struct *p, | |||
| 5934 | } else if (!strcmp(name, "fscreate")) { | 5931 | } else if (!strcmp(name, "fscreate")) { |
| 5935 | tsec->create_sid = sid; | 5932 | tsec->create_sid = sid; |
| 5936 | } else if (!strcmp(name, "keycreate")) { | 5933 | } else if (!strcmp(name, "keycreate")) { |
| 5937 | error = may_create_key(sid, p); | 5934 | error = avc_has_perm(mysid, sid, SECCLASS_KEY, KEY__CREATE, |
| 5935 | NULL); | ||
| 5938 | if (error) | 5936 | if (error) |
| 5939 | goto abort_change; | 5937 | goto abort_change; |
| 5940 | tsec->keycreate_sid = sid; | 5938 | tsec->keycreate_sid = sid; |
| @@ -5961,7 +5959,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
| 5961 | 5959 | ||
| 5962 | /* Check for ptracing, and update the task SID if ok. | 5960 | /* Check for ptracing, and update the task SID if ok. |
| 5963 | Otherwise, leave SID unchanged and fail. */ | 5961 | Otherwise, leave SID unchanged and fail. */ |
| 5964 | ptsid = ptrace_parent_sid(p); | 5962 | ptsid = ptrace_parent_sid(); |
| 5965 | if (ptsid != 0) { | 5963 | if (ptsid != 0) { |
| 5966 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, | 5964 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, |
| 5967 | PROCESS__PTRACE, NULL); | 5965 | PROCESS__PTRACE, NULL); |
| @@ -6209,7 +6207,6 @@ static struct security_hook_list selinux_hooks[] = { | |||
| 6209 | LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler), | 6207 | LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler), |
| 6210 | LSM_HOOK_INIT(task_movememory, selinux_task_movememory), | 6208 | LSM_HOOK_INIT(task_movememory, selinux_task_movememory), |
| 6211 | LSM_HOOK_INIT(task_kill, selinux_task_kill), | 6209 | LSM_HOOK_INIT(task_kill, selinux_task_kill), |
| 6212 | LSM_HOOK_INIT(task_wait, selinux_task_wait), | ||
| 6213 | LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode), | 6210 | LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode), |
| 6214 | 6211 | ||
| 6215 | LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission), | 6212 | LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission), |
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 13ae49b0baa0..7898ffa6d3e6 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h | |||
| @@ -171,5 +171,67 @@ struct security_class_mapping secclass_map[] = { | |||
| 171 | { COMMON_CAP_PERMS, NULL } }, | 171 | { COMMON_CAP_PERMS, NULL } }, |
| 172 | { "cap2_userns", | 172 | { "cap2_userns", |
| 173 | { COMMON_CAP2_PERMS, NULL } }, | 173 | { COMMON_CAP2_PERMS, NULL } }, |
| 174 | { "sctp_socket", | ||
| 175 | { COMMON_SOCK_PERMS, | ||
| 176 | "node_bind", NULL } }, | ||
| 177 | { "icmp_socket", | ||
| 178 | { COMMON_SOCK_PERMS, | ||
| 179 | "node_bind", NULL } }, | ||
| 180 | { "ax25_socket", | ||
| 181 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 182 | { "ipx_socket", | ||
| 183 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 184 | { "netrom_socket", | ||
| 185 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 186 | { "atmpvc_socket", | ||
| 187 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 188 | { "x25_socket", | ||
| 189 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 190 | { "rose_socket", | ||
| 191 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 192 | { "decnet_socket", | ||
| 193 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 194 | { "atmsvc_socket", | ||
| 195 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 196 | { "rds_socket", | ||
| 197 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 198 | { "irda_socket", | ||
| 199 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 200 | { "pppox_socket", | ||
| 201 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 202 | { "llc_socket", | ||
| 203 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 204 | { "can_socket", | ||
| 205 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 206 | { "tipc_socket", | ||
| 207 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 208 | { "bluetooth_socket", | ||
| 209 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 210 | { "iucv_socket", | ||
| 211 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 212 | { "rxrpc_socket", | ||
| 213 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 214 | { "isdn_socket", | ||
| 215 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 216 | { "phonet_socket", | ||
| 217 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 218 | { "ieee802154_socket", | ||
| 219 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 220 | { "caif_socket", | ||
| 221 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 222 | { "alg_socket", | ||
| 223 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 224 | { "nfc_socket", | ||
| 225 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 226 | { "vsock_socket", | ||
| 227 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 228 | { "kcm_socket", | ||
| 229 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 230 | { "qipcrtr_socket", | ||
| 231 | { COMMON_SOCK_PERMS, NULL } }, | ||
| 174 | { NULL } | 232 | { NULL } |
| 175 | }; | 233 | }; |
| 234 | |||
| 235 | #if PF_MAX > 43 | ||
| 236 | #error New address family defined, please update secclass_map. | ||
| 237 | #endif | ||
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index e8dab0f02c72..c03cdcd12a3b 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
| @@ -37,6 +37,16 @@ struct task_security_struct { | |||
| 37 | u32 sockcreate_sid; /* fscreate SID */ | 37 | u32 sockcreate_sid; /* fscreate SID */ |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | /* | ||
| 41 | * get the subjective security ID of the current task | ||
| 42 | */ | ||
| 43 | static inline u32 current_sid(void) | ||
| 44 | { | ||
| 45 | const struct task_security_struct *tsec = current_security(); | ||
| 46 | |||
| 47 | return tsec->sid; | ||
| 48 | } | ||
| 49 | |||
| 40 | enum label_initialized { | 50 | enum label_initialized { |
| 41 | LABEL_INVALID, /* invalid or not initialized */ | 51 | LABEL_INVALID, /* invalid or not initialized */ |
| 42 | LABEL_INITIALIZED, /* initialized */ | 52 | LABEL_INITIALIZED, /* initialized */ |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 308a286c6cbe..beaa14b8b6cf 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
| @@ -69,7 +69,7 @@ extern int selinux_enabled; | |||
| 69 | enum { | 69 | enum { |
| 70 | POLICYDB_CAPABILITY_NETPEER, | 70 | POLICYDB_CAPABILITY_NETPEER, |
| 71 | POLICYDB_CAPABILITY_OPENPERM, | 71 | POLICYDB_CAPABILITY_OPENPERM, |
| 72 | POLICYDB_CAPABILITY_REDHAT1, | 72 | POLICYDB_CAPABILITY_EXTSOCKCLASS, |
| 73 | POLICYDB_CAPABILITY_ALWAYSNETWORK, | 73 | POLICYDB_CAPABILITY_ALWAYSNETWORK, |
| 74 | __POLICYDB_CAPABILITY_MAX | 74 | __POLICYDB_CAPABILITY_MAX |
| 75 | }; | 75 | }; |
| @@ -77,6 +77,7 @@ enum { | |||
| 77 | 77 | ||
| 78 | extern int selinux_policycap_netpeer; | 78 | extern int selinux_policycap_netpeer; |
| 79 | extern int selinux_policycap_openperm; | 79 | extern int selinux_policycap_openperm; |
| 80 | extern int selinux_policycap_extsockclass; | ||
| 80 | extern int selinux_policycap_alwaysnetwork; | 81 | extern int selinux_policycap_alwaysnetwork; |
| 81 | 82 | ||
| 82 | /* | 83 | /* |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index cf9293e01fc1..c354807381c1 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -45,7 +45,7 @@ | |||
| 45 | static char *policycap_names[] = { | 45 | static char *policycap_names[] = { |
| 46 | "network_peer_controls", | 46 | "network_peer_controls", |
| 47 | "open_perms", | 47 | "open_perms", |
| 48 | "redhat1", | 48 | "extended_socket_class", |
| 49 | "always_check_network" | 49 | "always_check_network" |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| @@ -77,25 +77,6 @@ static char policy_opened; | |||
| 77 | /* global data for policy capabilities */ | 77 | /* global data for policy capabilities */ |
| 78 | static struct dentry *policycap_dir; | 78 | static struct dentry *policycap_dir; |
| 79 | 79 | ||
| 80 | /* Check whether a task is allowed to use a security operation. */ | ||
| 81 | static int task_has_security(struct task_struct *tsk, | ||
| 82 | u32 perms) | ||
| 83 | { | ||
| 84 | const struct task_security_struct *tsec; | ||
| 85 | u32 sid = 0; | ||
| 86 | |||
| 87 | rcu_read_lock(); | ||
| 88 | tsec = __task_cred(tsk)->security; | ||
| 89 | if (tsec) | ||
| 90 | sid = tsec->sid; | ||
| 91 | rcu_read_unlock(); | ||
| 92 | if (!tsec) | ||
| 93 | return -EACCES; | ||
| 94 | |||
| 95 | return avc_has_perm(sid, SECINITSID_SECURITY, | ||
| 96 | SECCLASS_SECURITY, perms, NULL); | ||
| 97 | } | ||
| 98 | |||
| 99 | enum sel_inos { | 80 | enum sel_inos { |
| 100 | SEL_ROOT_INO = 2, | 81 | SEL_ROOT_INO = 2, |
| 101 | SEL_LOAD, /* load policy */ | 82 | SEL_LOAD, /* load policy */ |
| @@ -166,7 +147,9 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, | |||
| 166 | new_value = !!new_value; | 147 | new_value = !!new_value; |
| 167 | 148 | ||
| 168 | if (new_value != selinux_enforcing) { | 149 | if (new_value != selinux_enforcing) { |
| 169 | length = task_has_security(current, SECURITY__SETENFORCE); | 150 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 151 | SECCLASS_SECURITY, SECURITY__SETENFORCE, | ||
| 152 | NULL); | ||
| 170 | if (length) | 153 | if (length) |
| 171 | goto out; | 154 | goto out; |
| 172 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, | 155 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, |
| @@ -368,7 +351,8 @@ static int sel_open_policy(struct inode *inode, struct file *filp) | |||
| 368 | 351 | ||
| 369 | mutex_lock(&sel_mutex); | 352 | mutex_lock(&sel_mutex); |
| 370 | 353 | ||
| 371 | rc = task_has_security(current, SECURITY__READ_POLICY); | 354 | rc = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 355 | SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); | ||
| 372 | if (rc) | 356 | if (rc) |
| 373 | goto err; | 357 | goto err; |
| 374 | 358 | ||
| @@ -429,7 +413,8 @@ static ssize_t sel_read_policy(struct file *filp, char __user *buf, | |||
| 429 | 413 | ||
| 430 | mutex_lock(&sel_mutex); | 414 | mutex_lock(&sel_mutex); |
| 431 | 415 | ||
| 432 | ret = task_has_security(current, SECURITY__READ_POLICY); | 416 | ret = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 417 | SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); | ||
| 433 | if (ret) | 418 | if (ret) |
| 434 | goto out; | 419 | goto out; |
| 435 | 420 | ||
| @@ -499,7 +484,8 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, | |||
| 499 | 484 | ||
| 500 | mutex_lock(&sel_mutex); | 485 | mutex_lock(&sel_mutex); |
| 501 | 486 | ||
| 502 | length = task_has_security(current, SECURITY__LOAD_POLICY); | 487 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 488 | SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL); | ||
| 503 | if (length) | 489 | if (length) |
| 504 | goto out; | 490 | goto out; |
| 505 | 491 | ||
| @@ -522,20 +508,28 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, | |||
| 522 | goto out; | 508 | goto out; |
| 523 | 509 | ||
| 524 | length = security_load_policy(data, count); | 510 | length = security_load_policy(data, count); |
| 525 | if (length) | 511 | if (length) { |
| 512 | pr_warn_ratelimited("SELinux: failed to load policy\n"); | ||
| 526 | goto out; | 513 | goto out; |
| 514 | } | ||
| 527 | 515 | ||
| 528 | length = sel_make_bools(); | 516 | length = sel_make_bools(); |
| 529 | if (length) | 517 | if (length) { |
| 518 | pr_err("SELinux: failed to load policy booleans\n"); | ||
| 530 | goto out1; | 519 | goto out1; |
| 520 | } | ||
| 531 | 521 | ||
| 532 | length = sel_make_classes(); | 522 | length = sel_make_classes(); |
| 533 | if (length) | 523 | if (length) { |
| 524 | pr_err("SELinux: failed to load policy classes\n"); | ||
| 534 | goto out1; | 525 | goto out1; |
| 526 | } | ||
| 535 | 527 | ||
| 536 | length = sel_make_policycap(); | 528 | length = sel_make_policycap(); |
| 537 | if (length) | 529 | if (length) { |
| 530 | pr_err("SELinux: failed to load policy capabilities\n"); | ||
| 538 | goto out1; | 531 | goto out1; |
| 532 | } | ||
| 539 | 533 | ||
| 540 | length = count; | 534 | length = count; |
| 541 | 535 | ||
| @@ -561,7 +555,8 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size) | |||
| 561 | u32 sid, len; | 555 | u32 sid, len; |
| 562 | ssize_t length; | 556 | ssize_t length; |
| 563 | 557 | ||
| 564 | length = task_has_security(current, SECURITY__CHECK_CONTEXT); | 558 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 559 | SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, NULL); | ||
| 565 | if (length) | 560 | if (length) |
| 566 | goto out; | 561 | goto out; |
| 567 | 562 | ||
| @@ -604,7 +599,9 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, | |||
| 604 | ssize_t length; | 599 | ssize_t length; |
| 605 | unsigned int new_value; | 600 | unsigned int new_value; |
| 606 | 601 | ||
| 607 | length = task_has_security(current, SECURITY__SETCHECKREQPROT); | 602 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 603 | SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, | ||
| 604 | NULL); | ||
| 608 | if (length) | 605 | if (length) |
| 609 | return length; | 606 | return length; |
| 610 | 607 | ||
| @@ -645,7 +642,8 @@ static ssize_t sel_write_validatetrans(struct file *file, | |||
| 645 | u16 tclass; | 642 | u16 tclass; |
| 646 | int rc; | 643 | int rc; |
| 647 | 644 | ||
| 648 | rc = task_has_security(current, SECURITY__VALIDATE_TRANS); | 645 | rc = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 646 | SECCLASS_SECURITY, SECURITY__VALIDATE_TRANS, NULL); | ||
| 649 | if (rc) | 647 | if (rc) |
| 650 | goto out; | 648 | goto out; |
| 651 | 649 | ||
| @@ -772,7 +770,8 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
| 772 | struct av_decision avd; | 770 | struct av_decision avd; |
| 773 | ssize_t length; | 771 | ssize_t length; |
| 774 | 772 | ||
| 775 | length = task_has_security(current, SECURITY__COMPUTE_AV); | 773 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 774 | SECCLASS_SECURITY, SECURITY__COMPUTE_AV, NULL); | ||
| 776 | if (length) | 775 | if (length) |
| 777 | goto out; | 776 | goto out; |
| 778 | 777 | ||
| @@ -822,7 +821,9 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
| 822 | u32 len; | 821 | u32 len; |
| 823 | int nargs; | 822 | int nargs; |
| 824 | 823 | ||
| 825 | length = task_has_security(current, SECURITY__COMPUTE_CREATE); | 824 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 825 | SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, | ||
| 826 | NULL); | ||
| 826 | if (length) | 827 | if (length) |
| 827 | goto out; | 828 | goto out; |
| 828 | 829 | ||
| @@ -919,7 +920,9 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | |||
| 919 | char *newcon = NULL; | 920 | char *newcon = NULL; |
| 920 | u32 len; | 921 | u32 len; |
| 921 | 922 | ||
| 922 | length = task_has_security(current, SECURITY__COMPUTE_RELABEL); | 923 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 924 | SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, | ||
| 925 | NULL); | ||
| 923 | if (length) | 926 | if (length) |
| 924 | goto out; | 927 | goto out; |
| 925 | 928 | ||
| @@ -975,7 +978,9 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
| 975 | int i, rc; | 978 | int i, rc; |
| 976 | u32 len, nsids; | 979 | u32 len, nsids; |
| 977 | 980 | ||
| 978 | length = task_has_security(current, SECURITY__COMPUTE_USER); | 981 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 982 | SECCLASS_SECURITY, SECURITY__COMPUTE_USER, | ||
| 983 | NULL); | ||
| 979 | if (length) | 984 | if (length) |
| 980 | goto out; | 985 | goto out; |
| 981 | 986 | ||
| @@ -1035,7 +1040,9 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | |||
| 1035 | char *newcon = NULL; | 1040 | char *newcon = NULL; |
| 1036 | u32 len; | 1041 | u32 len; |
| 1037 | 1042 | ||
| 1038 | length = task_has_security(current, SECURITY__COMPUTE_MEMBER); | 1043 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 1044 | SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, | ||
| 1045 | NULL); | ||
| 1039 | if (length) | 1046 | if (length) |
| 1040 | goto out; | 1047 | goto out; |
| 1041 | 1048 | ||
| @@ -1142,7 +1149,9 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
| 1142 | 1149 | ||
| 1143 | mutex_lock(&sel_mutex); | 1150 | mutex_lock(&sel_mutex); |
| 1144 | 1151 | ||
| 1145 | length = task_has_security(current, SECURITY__SETBOOL); | 1152 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 1153 | SECCLASS_SECURITY, SECURITY__SETBOOL, | ||
| 1154 | NULL); | ||
| 1146 | if (length) | 1155 | if (length) |
| 1147 | goto out; | 1156 | goto out; |
| 1148 | 1157 | ||
| @@ -1198,7 +1207,9 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
| 1198 | 1207 | ||
| 1199 | mutex_lock(&sel_mutex); | 1208 | mutex_lock(&sel_mutex); |
| 1200 | 1209 | ||
| 1201 | length = task_has_security(current, SECURITY__SETBOOL); | 1210 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 1211 | SECCLASS_SECURITY, SECURITY__SETBOOL, | ||
| 1212 | NULL); | ||
| 1202 | if (length) | 1213 | if (length) |
| 1203 | goto out; | 1214 | goto out; |
| 1204 | 1215 | ||
| @@ -1299,8 +1310,11 @@ static int sel_make_bools(void) | |||
| 1299 | 1310 | ||
| 1300 | isec = (struct inode_security_struct *)inode->i_security; | 1311 | isec = (struct inode_security_struct *)inode->i_security; |
| 1301 | ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid); | 1312 | ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid); |
| 1302 | if (ret) | 1313 | if (ret) { |
| 1303 | goto out; | 1314 | pr_warn_ratelimited("SELinux: no sid found, defaulting to security isid for %s\n", |
| 1315 | page); | ||
| 1316 | sid = SECINITSID_SECURITY; | ||
| 1317 | } | ||
| 1304 | 1318 | ||
| 1305 | isec->sid = sid; | 1319 | isec->sid = sid; |
| 1306 | isec->initialized = LABEL_INITIALIZED; | 1320 | isec->initialized = LABEL_INITIALIZED; |
| @@ -1351,7 +1365,9 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, | |||
| 1351 | ssize_t ret; | 1365 | ssize_t ret; |
| 1352 | unsigned int new_value; | 1366 | unsigned int new_value; |
| 1353 | 1367 | ||
| 1354 | ret = task_has_security(current, SECURITY__SETSECPARAM); | 1368 | ret = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
| 1369 | SECCLASS_SECURITY, SECURITY__SETSECPARAM, | ||
| 1370 | NULL); | ||
| 1355 | if (ret) | 1371 | if (ret) |
| 1356 | return ret; | 1372 | return ret; |
| 1357 | 1373 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 082b20c78363..a70fcee9824b 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -72,6 +72,7 @@ | |||
| 72 | 72 | ||
| 73 | int selinux_policycap_netpeer; | 73 | int selinux_policycap_netpeer; |
| 74 | int selinux_policycap_openperm; | 74 | int selinux_policycap_openperm; |
| 75 | int selinux_policycap_extsockclass; | ||
| 75 | int selinux_policycap_alwaysnetwork; | 76 | int selinux_policycap_alwaysnetwork; |
| 76 | 77 | ||
| 77 | static DEFINE_RWLOCK(policy_rwlock); | 78 | static DEFINE_RWLOCK(policy_rwlock); |
| @@ -1988,6 +1989,8 @@ static void security_load_policycaps(void) | |||
| 1988 | POLICYDB_CAPABILITY_NETPEER); | 1989 | POLICYDB_CAPABILITY_NETPEER); |
| 1989 | selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps, | 1990 | selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps, |
| 1990 | POLICYDB_CAPABILITY_OPENPERM); | 1991 | POLICYDB_CAPABILITY_OPENPERM); |
| 1992 | selinux_policycap_extsockclass = ebitmap_get_bit(&policydb.policycaps, | ||
| 1993 | POLICYDB_CAPABILITY_EXTSOCKCLASS); | ||
| 1991 | selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps, | 1994 | selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps, |
| 1992 | POLICYDB_CAPABILITY_ALWAYSNETWORK); | 1995 | POLICYDB_CAPABILITY_ALWAYSNETWORK); |
| 1993 | } | 1996 | } |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 1723bd370e3a..60b4217b9b68 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -2302,25 +2302,6 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
| 2302 | } | 2302 | } |
| 2303 | 2303 | ||
| 2304 | /** | 2304 | /** |
| 2305 | * smack_task_wait - Smack access check for waiting | ||
| 2306 | * @p: task to wait for | ||
| 2307 | * | ||
| 2308 | * Returns 0 | ||
| 2309 | */ | ||
| 2310 | static int smack_task_wait(struct task_struct *p) | ||
| 2311 | { | ||
| 2312 | /* | ||
| 2313 | * Allow the operation to succeed. | ||
| 2314 | * Zombies are bad. | ||
| 2315 | * In userless environments (e.g. phones) programs | ||
| 2316 | * get marked with SMACK64EXEC and even if the parent | ||
| 2317 | * and child shouldn't be talking the parent still | ||
| 2318 | * may expect to know when the child exits. | ||
| 2319 | */ | ||
| 2320 | return 0; | ||
| 2321 | } | ||
| 2322 | |||
| 2323 | /** | ||
| 2324 | * smack_task_to_inode - copy task smack into the inode blob | 2305 | * smack_task_to_inode - copy task smack into the inode blob |
| 2325 | * @p: task to copy from | 2306 | * @p: task to copy from |
| 2326 | * @inode: inode to copy to | 2307 | * @inode: inode to copy to |
| @@ -3680,7 +3661,6 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
| 3680 | 3661 | ||
| 3681 | /** | 3662 | /** |
| 3682 | * smack_setprocattr - Smack process attribute setting | 3663 | * smack_setprocattr - Smack process attribute setting |
| 3683 | * @p: the object task | ||
| 3684 | * @name: the name of the attribute in /proc/.../attr | 3664 | * @name: the name of the attribute in /proc/.../attr |
| 3685 | * @value: the value to set | 3665 | * @value: the value to set |
| 3686 | * @size: the size of the value | 3666 | * @size: the size of the value |
| @@ -3690,8 +3670,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
| 3690 | * | 3670 | * |
| 3691 | * Returns the length of the smack label or an error code | 3671 | * Returns the length of the smack label or an error code |
| 3692 | */ | 3672 | */ |
| 3693 | static int smack_setprocattr(struct task_struct *p, char *name, | 3673 | static int smack_setprocattr(const char *name, void *value, size_t size) |
| 3694 | void *value, size_t size) | ||
| 3695 | { | 3674 | { |
| 3696 | struct task_smack *tsp = current_security(); | 3675 | struct task_smack *tsp = current_security(); |
| 3697 | struct cred *new; | 3676 | struct cred *new; |
| @@ -3699,13 +3678,6 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
| 3699 | struct smack_known_list_elem *sklep; | 3678 | struct smack_known_list_elem *sklep; |
| 3700 | int rc; | 3679 | int rc; |
| 3701 | 3680 | ||
| 3702 | /* | ||
| 3703 | * Changing another process' Smack value is too dangerous | ||
| 3704 | * and supports no sane use case. | ||
| 3705 | */ | ||
| 3706 | if (p != current) | ||
| 3707 | return -EPERM; | ||
| 3708 | |||
| 3709 | if (!smack_privileged(CAP_MAC_ADMIN) && list_empty(&tsp->smk_relabel)) | 3681 | if (!smack_privileged(CAP_MAC_ADMIN) && list_empty(&tsp->smk_relabel)) |
| 3710 | return -EPERM; | 3682 | return -EPERM; |
| 3711 | 3683 | ||
| @@ -4727,7 +4699,6 @@ static struct security_hook_list smack_hooks[] = { | |||
| 4727 | LSM_HOOK_INIT(task_getscheduler, smack_task_getscheduler), | 4699 | LSM_HOOK_INIT(task_getscheduler, smack_task_getscheduler), |
| 4728 | LSM_HOOK_INIT(task_movememory, smack_task_movememory), | 4700 | LSM_HOOK_INIT(task_movememory, smack_task_movememory), |
| 4729 | LSM_HOOK_INIT(task_kill, smack_task_kill), | 4701 | LSM_HOOK_INIT(task_kill, smack_task_kill), |
| 4730 | LSM_HOOK_INIT(task_wait, smack_task_wait), | ||
| 4731 | LSM_HOOK_INIT(task_to_inode, smack_task_to_inode), | 4702 | LSM_HOOK_INIT(task_to_inode, smack_task_to_inode), |
| 4732 | 4703 | ||
| 4733 | LSM_HOOK_INIT(ipc_permission, smack_ipc_permission), | 4704 | LSM_HOOK_INIT(ipc_permission, smack_ipc_permission), |
