diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 395 |
1 files changed, 198 insertions, 197 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d98550abe16d..0c2ac318aa7f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -28,7 +28,8 @@ | |||
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/tracehook.h> | 29 | #include <linux/tracehook.h> |
30 | #include <linux/errno.h> | 30 | #include <linux/errno.h> |
31 | #include <linux/sched.h> | 31 | #include <linux/sched/signal.h> |
32 | #include <linux/sched/task.h> | ||
32 | #include <linux/lsm_hooks.h> | 33 | #include <linux/lsm_hooks.h> |
33 | #include <linux/xattr.h> | 34 | #include <linux/xattr.h> |
34 | #include <linux/capability.h> | 35 | #include <linux/capability.h> |
@@ -210,16 +211,6 @@ static inline u32 task_sid(const struct task_struct *task) | |||
210 | return sid; | 211 | return sid; |
211 | } | 212 | } |
212 | 213 | ||
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. */ | 214 | /* Allocate and free functions for each kind of security blob. */ |
224 | 215 | ||
225 | static int inode_alloc_security(struct inode *inode) | 216 | static int inode_alloc_security(struct inode *inode) |
@@ -492,7 +483,11 @@ static int selinux_is_sblabel_mnt(struct super_block *sb) | |||
492 | !strcmp(sb->s_type->name, "sysfs") || | 483 | !strcmp(sb->s_type->name, "sysfs") || |
493 | !strcmp(sb->s_type->name, "pstore") || | 484 | !strcmp(sb->s_type->name, "pstore") || |
494 | !strcmp(sb->s_type->name, "debugfs") || | 485 | !strcmp(sb->s_type->name, "debugfs") || |
495 | !strcmp(sb->s_type->name, "rootfs"); | 486 | !strcmp(sb->s_type->name, "tracefs") || |
487 | !strcmp(sb->s_type->name, "rootfs") || | ||
488 | (selinux_policycap_cgroupseclabel && | ||
489 | (!strcmp(sb->s_type->name, "cgroup") || | ||
490 | !strcmp(sb->s_type->name, "cgroup2"))); | ||
496 | } | 491 | } |
497 | 492 | ||
498 | static int sb_finish_set_opts(struct super_block *sb) | 493 | static int sb_finish_set_opts(struct super_block *sb) |
@@ -833,10 +828,14 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
833 | } | 828 | } |
834 | 829 | ||
835 | /* | 830 | /* |
836 | * If this is a user namespace mount, no contexts are allowed | 831 | * If this is a user namespace mount and the filesystem type is not |
837 | * on the command line and security labels must be ignored. | 832 | * explicitly whitelisted, then no contexts are allowed on the command |
833 | * line and security labels must be ignored. | ||
838 | */ | 834 | */ |
839 | if (sb->s_user_ns != &init_user_ns) { | 835 | if (sb->s_user_ns != &init_user_ns && |
836 | strcmp(sb->s_type->name, "tmpfs") && | ||
837 | strcmp(sb->s_type->name, "ramfs") && | ||
838 | strcmp(sb->s_type->name, "devpts")) { | ||
840 | if (context_sid || fscontext_sid || rootcontext_sid || | 839 | if (context_sid || fscontext_sid || rootcontext_sid || |
841 | defcontext_sid) { | 840 | defcontext_sid) { |
842 | rc = -EACCES; | 841 | rc = -EACCES; |
@@ -1268,6 +1267,8 @@ static inline int default_protocol_dgram(int protocol) | |||
1268 | 1267 | ||
1269 | static inline u16 socket_type_to_security_class(int family, int type, int protocol) | 1268 | static inline u16 socket_type_to_security_class(int family, int type, int protocol) |
1270 | { | 1269 | { |
1270 | int extsockclass = selinux_policycap_extsockclass; | ||
1271 | |||
1271 | switch (family) { | 1272 | switch (family) { |
1272 | case PF_UNIX: | 1273 | case PF_UNIX: |
1273 | switch (type) { | 1274 | switch (type) { |
@@ -1282,13 +1283,19 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc | |||
1282 | case PF_INET6: | 1283 | case PF_INET6: |
1283 | switch (type) { | 1284 | switch (type) { |
1284 | case SOCK_STREAM: | 1285 | case SOCK_STREAM: |
1286 | case SOCK_SEQPACKET: | ||
1285 | if (default_protocol_stream(protocol)) | 1287 | if (default_protocol_stream(protocol)) |
1286 | return SECCLASS_TCP_SOCKET; | 1288 | return SECCLASS_TCP_SOCKET; |
1289 | else if (extsockclass && protocol == IPPROTO_SCTP) | ||
1290 | return SECCLASS_SCTP_SOCKET; | ||
1287 | else | 1291 | else |
1288 | return SECCLASS_RAWIP_SOCKET; | 1292 | return SECCLASS_RAWIP_SOCKET; |
1289 | case SOCK_DGRAM: | 1293 | case SOCK_DGRAM: |
1290 | if (default_protocol_dgram(protocol)) | 1294 | if (default_protocol_dgram(protocol)) |
1291 | return SECCLASS_UDP_SOCKET; | 1295 | return SECCLASS_UDP_SOCKET; |
1296 | else if (extsockclass && (protocol == IPPROTO_ICMP || | ||
1297 | protocol == IPPROTO_ICMPV6)) | ||
1298 | return SECCLASS_ICMP_SOCKET; | ||
1292 | else | 1299 | else |
1293 | return SECCLASS_RAWIP_SOCKET; | 1300 | return SECCLASS_RAWIP_SOCKET; |
1294 | case SOCK_DCCP: | 1301 | case SOCK_DCCP: |
@@ -1342,6 +1349,68 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc | |||
1342 | return SECCLASS_APPLETALK_SOCKET; | 1349 | return SECCLASS_APPLETALK_SOCKET; |
1343 | } | 1350 | } |
1344 | 1351 | ||
1352 | if (extsockclass) { | ||
1353 | switch (family) { | ||
1354 | case PF_AX25: | ||
1355 | return SECCLASS_AX25_SOCKET; | ||
1356 | case PF_IPX: | ||
1357 | return SECCLASS_IPX_SOCKET; | ||
1358 | case PF_NETROM: | ||
1359 | return SECCLASS_NETROM_SOCKET; | ||
1360 | case PF_ATMPVC: | ||
1361 | return SECCLASS_ATMPVC_SOCKET; | ||
1362 | case PF_X25: | ||
1363 | return SECCLASS_X25_SOCKET; | ||
1364 | case PF_ROSE: | ||
1365 | return SECCLASS_ROSE_SOCKET; | ||
1366 | case PF_DECnet: | ||
1367 | return SECCLASS_DECNET_SOCKET; | ||
1368 | case PF_ATMSVC: | ||
1369 | return SECCLASS_ATMSVC_SOCKET; | ||
1370 | case PF_RDS: | ||
1371 | return SECCLASS_RDS_SOCKET; | ||
1372 | case PF_IRDA: | ||
1373 | return SECCLASS_IRDA_SOCKET; | ||
1374 | case PF_PPPOX: | ||
1375 | return SECCLASS_PPPOX_SOCKET; | ||
1376 | case PF_LLC: | ||
1377 | return SECCLASS_LLC_SOCKET; | ||
1378 | case PF_CAN: | ||
1379 | return SECCLASS_CAN_SOCKET; | ||
1380 | case PF_TIPC: | ||
1381 | return SECCLASS_TIPC_SOCKET; | ||
1382 | case PF_BLUETOOTH: | ||
1383 | return SECCLASS_BLUETOOTH_SOCKET; | ||
1384 | case PF_IUCV: | ||
1385 | return SECCLASS_IUCV_SOCKET; | ||
1386 | case PF_RXRPC: | ||
1387 | return SECCLASS_RXRPC_SOCKET; | ||
1388 | case PF_ISDN: | ||
1389 | return SECCLASS_ISDN_SOCKET; | ||
1390 | case PF_PHONET: | ||
1391 | return SECCLASS_PHONET_SOCKET; | ||
1392 | case PF_IEEE802154: | ||
1393 | return SECCLASS_IEEE802154_SOCKET; | ||
1394 | case PF_CAIF: | ||
1395 | return SECCLASS_CAIF_SOCKET; | ||
1396 | case PF_ALG: | ||
1397 | return SECCLASS_ALG_SOCKET; | ||
1398 | case PF_NFC: | ||
1399 | return SECCLASS_NFC_SOCKET; | ||
1400 | case PF_VSOCK: | ||
1401 | return SECCLASS_VSOCK_SOCKET; | ||
1402 | case PF_KCM: | ||
1403 | return SECCLASS_KCM_SOCKET; | ||
1404 | case PF_QIPCRTR: | ||
1405 | return SECCLASS_QIPCRTR_SOCKET; | ||
1406 | case PF_SMC: | ||
1407 | return SECCLASS_SMC_SOCKET; | ||
1408 | #if PF_MAX > 44 | ||
1409 | #error New address family defined, please update this function. | ||
1410 | #endif | ||
1411 | } | ||
1412 | } | ||
1413 | |||
1345 | return SECCLASS_SOCKET; | 1414 | return SECCLASS_SOCKET; |
1346 | } | 1415 | } |
1347 | 1416 | ||
@@ -1608,55 +1677,6 @@ static inline u32 signal_to_av(int sig) | |||
1608 | return perm; | 1677 | return perm; |
1609 | } | 1678 | } |
1610 | 1679 | ||
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 | 1680 | #if CAP_LAST_CAP > 63 |
1661 | #error Fix SELinux to handle capabilities > 63. | 1681 | #error Fix SELinux to handle capabilities > 63. |
1662 | #endif | 1682 | #endif |
@@ -1698,16 +1718,6 @@ static int cred_has_capability(const struct cred *cred, | |||
1698 | return rc; | 1718 | return rc; |
1699 | } | 1719 | } |
1700 | 1720 | ||
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. | 1721 | /* Check whether a task has a particular permission to an inode. |
1712 | The 'adp' parameter is optional and allows other audit | 1722 | The 'adp' parameter is optional and allows other audit |
1713 | data to be passed (e.g. the dentry). */ | 1723 | data to be passed (e.g. the dentry). */ |
@@ -1879,15 +1889,6 @@ static int may_create(struct inode *dir, | |||
1879 | FILESYSTEM__ASSOCIATE, &ad); | 1889 | FILESYSTEM__ASSOCIATE, &ad); |
1880 | } | 1890 | } |
1881 | 1891 | ||
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 | 1892 | #define MAY_LINK 0 |
1892 | #define MAY_UNLINK 1 | 1893 | #define MAY_UNLINK 1 |
1893 | #define MAY_RMDIR 2 | 1894 | #define MAY_RMDIR 2 |
@@ -2143,24 +2144,26 @@ static int selinux_binder_transfer_file(struct task_struct *from, | |||
2143 | static int selinux_ptrace_access_check(struct task_struct *child, | 2144 | static int selinux_ptrace_access_check(struct task_struct *child, |
2144 | unsigned int mode) | 2145 | unsigned int mode) |
2145 | { | 2146 | { |
2146 | if (mode & PTRACE_MODE_READ) { | 2147 | u32 sid = current_sid(); |
2147 | u32 sid = current_sid(); | 2148 | u32 csid = task_sid(child); |
2148 | u32 csid = task_sid(child); | 2149 | |
2150 | if (mode & PTRACE_MODE_READ) | ||
2149 | return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); | 2151 | return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); |
2150 | } | ||
2151 | 2152 | ||
2152 | return current_has_perm(child, PROCESS__PTRACE); | 2153 | return avc_has_perm(sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); |
2153 | } | 2154 | } |
2154 | 2155 | ||
2155 | static int selinux_ptrace_traceme(struct task_struct *parent) | 2156 | static int selinux_ptrace_traceme(struct task_struct *parent) |
2156 | { | 2157 | { |
2157 | return task_has_perm(parent, current, PROCESS__PTRACE); | 2158 | return avc_has_perm(task_sid(parent), current_sid(), SECCLASS_PROCESS, |
2159 | PROCESS__PTRACE, NULL); | ||
2158 | } | 2160 | } |
2159 | 2161 | ||
2160 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, | 2162 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, |
2161 | kernel_cap_t *inheritable, kernel_cap_t *permitted) | 2163 | kernel_cap_t *inheritable, kernel_cap_t *permitted) |
2162 | { | 2164 | { |
2163 | return current_has_perm(target, PROCESS__GETCAP); | 2165 | return avc_has_perm(current_sid(), task_sid(target), SECCLASS_PROCESS, |
2166 | PROCESS__GETCAP, NULL); | ||
2164 | } | 2167 | } |
2165 | 2168 | ||
2166 | static int selinux_capset(struct cred *new, const struct cred *old, | 2169 | static int selinux_capset(struct cred *new, const struct cred *old, |
@@ -2168,7 +2171,8 @@ static int selinux_capset(struct cred *new, const struct cred *old, | |||
2168 | const kernel_cap_t *inheritable, | 2171 | const kernel_cap_t *inheritable, |
2169 | const kernel_cap_t *permitted) | 2172 | const kernel_cap_t *permitted) |
2170 | { | 2173 | { |
2171 | return cred_has_perm(old, new, PROCESS__SETCAP); | 2174 | return avc_has_perm(cred_sid(old), cred_sid(new), SECCLASS_PROCESS, |
2175 | PROCESS__SETCAP, NULL); | ||
2172 | } | 2176 | } |
2173 | 2177 | ||
2174 | /* | 2178 | /* |
@@ -2224,29 +2228,22 @@ static int selinux_quota_on(struct dentry *dentry) | |||
2224 | 2228 | ||
2225 | static int selinux_syslog(int type) | 2229 | static int selinux_syslog(int type) |
2226 | { | 2230 | { |
2227 | int rc; | ||
2228 | |||
2229 | switch (type) { | 2231 | switch (type) { |
2230 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ | 2232 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ |
2231 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ | 2233 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ |
2232 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); | 2234 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, |
2233 | break; | 2235 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL); |
2234 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ | 2236 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ |
2235 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ | 2237 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ |
2236 | /* Set level of messages printed to console */ | 2238 | /* Set level of messages printed to console */ |
2237 | case SYSLOG_ACTION_CONSOLE_LEVEL: | 2239 | case SYSLOG_ACTION_CONSOLE_LEVEL: |
2238 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); | 2240 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, |
2239 | break; | 2241 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, |
2240 | case SYSLOG_ACTION_CLOSE: /* Close log */ | 2242 | 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 | } | 2243 | } |
2249 | return rc; | 2244 | /* All other syslog types */ |
2245 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, | ||
2246 | SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL); | ||
2250 | } | 2247 | } |
2251 | 2248 | ||
2252 | /* | 2249 | /* |
@@ -2271,13 +2268,13 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | |||
2271 | 2268 | ||
2272 | /* binprm security operations */ | 2269 | /* binprm security operations */ |
2273 | 2270 | ||
2274 | static u32 ptrace_parent_sid(struct task_struct *task) | 2271 | static u32 ptrace_parent_sid(void) |
2275 | { | 2272 | { |
2276 | u32 sid = 0; | 2273 | u32 sid = 0; |
2277 | struct task_struct *tracer; | 2274 | struct task_struct *tracer; |
2278 | 2275 | ||
2279 | rcu_read_lock(); | 2276 | rcu_read_lock(); |
2280 | tracer = ptrace_parent(task); | 2277 | tracer = ptrace_parent(current); |
2281 | if (tracer) | 2278 | if (tracer) |
2282 | sid = task_sid(tracer); | 2279 | sid = task_sid(tracer); |
2283 | rcu_read_unlock(); | 2280 | rcu_read_unlock(); |
@@ -2404,9 +2401,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2404 | 2401 | ||
2405 | /* Make sure that anyone attempting to ptrace over a task that | 2402 | /* Make sure that anyone attempting to ptrace over a task that |
2406 | * changes its SID has the appropriate permit */ | 2403 | * changes its SID has the appropriate permit */ |
2407 | if (bprm->unsafe & | 2404 | if (bprm->unsafe & LSM_UNSAFE_PTRACE) { |
2408 | (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { | 2405 | u32 ptsid = ptrace_parent_sid(); |
2409 | u32 ptsid = ptrace_parent_sid(current); | ||
2410 | if (ptsid != 0) { | 2406 | if (ptsid != 0) { |
2411 | rc = avc_has_perm(ptsid, new_tsec->sid, | 2407 | rc = avc_has_perm(ptsid, new_tsec->sid, |
2412 | SECCLASS_PROCESS, | 2408 | SECCLASS_PROCESS, |
@@ -3503,6 +3499,7 @@ static int default_noexec; | |||
3503 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 3499 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
3504 | { | 3500 | { |
3505 | const struct cred *cred = current_cred(); | 3501 | const struct cred *cred = current_cred(); |
3502 | u32 sid = cred_sid(cred); | ||
3506 | int rc = 0; | 3503 | int rc = 0; |
3507 | 3504 | ||
3508 | if (default_noexec && | 3505 | if (default_noexec && |
@@ -3513,7 +3510,8 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
3513 | * private file mapping that will also be writable. | 3510 | * private file mapping that will also be writable. |
3514 | * This has an additional check. | 3511 | * This has an additional check. |
3515 | */ | 3512 | */ |
3516 | rc = cred_has_perm(cred, cred, PROCESS__EXECMEM); | 3513 | rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, |
3514 | PROCESS__EXECMEM, NULL); | ||
3517 | if (rc) | 3515 | if (rc) |
3518 | goto error; | 3516 | goto error; |
3519 | } | 3517 | } |
@@ -3564,6 +3562,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3564 | unsigned long prot) | 3562 | unsigned long prot) |
3565 | { | 3563 | { |
3566 | const struct cred *cred = current_cred(); | 3564 | const struct cred *cred = current_cred(); |
3565 | u32 sid = cred_sid(cred); | ||
3567 | 3566 | ||
3568 | if (selinux_checkreqprot) | 3567 | if (selinux_checkreqprot) |
3569 | prot = reqprot; | 3568 | prot = reqprot; |
@@ -3573,12 +3572,14 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3573 | int rc = 0; | 3572 | int rc = 0; |
3574 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3573 | if (vma->vm_start >= vma->vm_mm->start_brk && |
3575 | vma->vm_end <= vma->vm_mm->brk) { | 3574 | vma->vm_end <= vma->vm_mm->brk) { |
3576 | rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); | 3575 | rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, |
3576 | PROCESS__EXECHEAP, NULL); | ||
3577 | } else if (!vma->vm_file && | 3577 | } else if (!vma->vm_file && |
3578 | ((vma->vm_start <= vma->vm_mm->start_stack && | 3578 | ((vma->vm_start <= vma->vm_mm->start_stack && |
3579 | vma->vm_end >= vma->vm_mm->start_stack) || | 3579 | vma->vm_end >= vma->vm_mm->start_stack) || |
3580 | vma_is_stack_for_current(vma))) { | 3580 | vma_is_stack_for_current(vma))) { |
3581 | rc = current_has_perm(current, PROCESS__EXECSTACK); | 3581 | rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, |
3582 | PROCESS__EXECSTACK, NULL); | ||
3582 | } else if (vma->vm_file && vma->anon_vma) { | 3583 | } else if (vma->vm_file && vma->anon_vma) { |
3583 | /* | 3584 | /* |
3584 | * We are making executable a file mapping that has | 3585 | * We are making executable a file mapping that has |
@@ -3711,7 +3712,9 @@ static int selinux_file_open(struct file *file, const struct cred *cred) | |||
3711 | 3712 | ||
3712 | static int selinux_task_create(unsigned long clone_flags) | 3713 | static int selinux_task_create(unsigned long clone_flags) |
3713 | { | 3714 | { |
3714 | return current_has_perm(current, PROCESS__FORK); | 3715 | u32 sid = current_sid(); |
3716 | |||
3717 | return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL); | ||
3715 | } | 3718 | } |
3716 | 3719 | ||
3717 | /* | 3720 | /* |
@@ -3821,15 +3824,12 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
3821 | 3824 | ||
3822 | static int selinux_kernel_module_request(char *kmod_name) | 3825 | static int selinux_kernel_module_request(char *kmod_name) |
3823 | { | 3826 | { |
3824 | u32 sid; | ||
3825 | struct common_audit_data ad; | 3827 | struct common_audit_data ad; |
3826 | 3828 | ||
3827 | sid = task_sid(current); | ||
3828 | |||
3829 | ad.type = LSM_AUDIT_DATA_KMOD; | 3829 | ad.type = LSM_AUDIT_DATA_KMOD; |
3830 | ad.u.kmod_name = kmod_name; | 3830 | ad.u.kmod_name = kmod_name; |
3831 | 3831 | ||
3832 | return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, | 3832 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, |
3833 | SYSTEM__MODULE_REQUEST, &ad); | 3833 | SYSTEM__MODULE_REQUEST, &ad); |
3834 | } | 3834 | } |
3835 | 3835 | ||
@@ -3881,17 +3881,20 @@ static int selinux_kernel_read_file(struct file *file, | |||
3881 | 3881 | ||
3882 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3882 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
3883 | { | 3883 | { |
3884 | return current_has_perm(p, PROCESS__SETPGID); | 3884 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
3885 | PROCESS__SETPGID, NULL); | ||
3885 | } | 3886 | } |
3886 | 3887 | ||
3887 | static int selinux_task_getpgid(struct task_struct *p) | 3888 | static int selinux_task_getpgid(struct task_struct *p) |
3888 | { | 3889 | { |
3889 | return current_has_perm(p, PROCESS__GETPGID); | 3890 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
3891 | PROCESS__GETPGID, NULL); | ||
3890 | } | 3892 | } |
3891 | 3893 | ||
3892 | static int selinux_task_getsid(struct task_struct *p) | 3894 | static int selinux_task_getsid(struct task_struct *p) |
3893 | { | 3895 | { |
3894 | return current_has_perm(p, PROCESS__GETSESSION); | 3896 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
3897 | PROCESS__GETSESSION, NULL); | ||
3895 | } | 3898 | } |
3896 | 3899 | ||
3897 | static void selinux_task_getsecid(struct task_struct *p, u32 *secid) | 3900 | static void selinux_task_getsecid(struct task_struct *p, u32 *secid) |
@@ -3901,17 +3904,20 @@ static void selinux_task_getsecid(struct task_struct *p, u32 *secid) | |||
3901 | 3904 | ||
3902 | static int selinux_task_setnice(struct task_struct *p, int nice) | 3905 | static int selinux_task_setnice(struct task_struct *p, int nice) |
3903 | { | 3906 | { |
3904 | return current_has_perm(p, PROCESS__SETSCHED); | 3907 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
3908 | PROCESS__SETSCHED, NULL); | ||
3905 | } | 3909 | } |
3906 | 3910 | ||
3907 | static int selinux_task_setioprio(struct task_struct *p, int ioprio) | 3911 | static int selinux_task_setioprio(struct task_struct *p, int ioprio) |
3908 | { | 3912 | { |
3909 | return current_has_perm(p, PROCESS__SETSCHED); | 3913 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
3914 | PROCESS__SETSCHED, NULL); | ||
3910 | } | 3915 | } |
3911 | 3916 | ||
3912 | static int selinux_task_getioprio(struct task_struct *p) | 3917 | static int selinux_task_getioprio(struct task_struct *p) |
3913 | { | 3918 | { |
3914 | return current_has_perm(p, PROCESS__GETSCHED); | 3919 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
3920 | PROCESS__GETSCHED, NULL); | ||
3915 | } | 3921 | } |
3916 | 3922 | ||
3917 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, | 3923 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, |
@@ -3924,47 +3930,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 | 3930 | later be used as a safe reset point for the soft limit |
3925 | upon context transitions. See selinux_bprm_committing_creds. */ | 3931 | upon context transitions. See selinux_bprm_committing_creds. */ |
3926 | if (old_rlim->rlim_max != new_rlim->rlim_max) | 3932 | if (old_rlim->rlim_max != new_rlim->rlim_max) |
3927 | return current_has_perm(p, PROCESS__SETRLIMIT); | 3933 | return avc_has_perm(current_sid(), task_sid(p), |
3934 | SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL); | ||
3928 | 3935 | ||
3929 | return 0; | 3936 | return 0; |
3930 | } | 3937 | } |
3931 | 3938 | ||
3932 | static int selinux_task_setscheduler(struct task_struct *p) | 3939 | static int selinux_task_setscheduler(struct task_struct *p) |
3933 | { | 3940 | { |
3934 | return current_has_perm(p, PROCESS__SETSCHED); | 3941 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
3942 | PROCESS__SETSCHED, NULL); | ||
3935 | } | 3943 | } |
3936 | 3944 | ||
3937 | static int selinux_task_getscheduler(struct task_struct *p) | 3945 | static int selinux_task_getscheduler(struct task_struct *p) |
3938 | { | 3946 | { |
3939 | return current_has_perm(p, PROCESS__GETSCHED); | 3947 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
3948 | PROCESS__GETSCHED, NULL); | ||
3940 | } | 3949 | } |
3941 | 3950 | ||
3942 | static int selinux_task_movememory(struct task_struct *p) | 3951 | static int selinux_task_movememory(struct task_struct *p) |
3943 | { | 3952 | { |
3944 | return current_has_perm(p, PROCESS__SETSCHED); | 3953 | return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, |
3954 | PROCESS__SETSCHED, NULL); | ||
3945 | } | 3955 | } |
3946 | 3956 | ||
3947 | static int selinux_task_kill(struct task_struct *p, struct siginfo *info, | 3957 | static int selinux_task_kill(struct task_struct *p, struct siginfo *info, |
3948 | int sig, u32 secid) | 3958 | int sig, u32 secid) |
3949 | { | 3959 | { |
3950 | u32 perm; | 3960 | u32 perm; |
3951 | int rc; | ||
3952 | 3961 | ||
3953 | if (!sig) | 3962 | if (!sig) |
3954 | perm = PROCESS__SIGNULL; /* null signal; existence test */ | 3963 | perm = PROCESS__SIGNULL; /* null signal; existence test */ |
3955 | else | 3964 | else |
3956 | perm = signal_to_av(sig); | 3965 | perm = signal_to_av(sig); |
3957 | if (secid) | 3966 | if (!secid) |
3958 | rc = avc_has_perm(secid, task_sid(p), | 3967 | secid = current_sid(); |
3959 | SECCLASS_PROCESS, perm, NULL); | 3968 | 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 | } | 3969 | } |
3969 | 3970 | ||
3970 | static void selinux_task_to_inode(struct task_struct *p, | 3971 | static void selinux_task_to_inode(struct task_struct *p, |
@@ -4254,12 +4255,11 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec, | |||
4254 | socksid); | 4255 | socksid); |
4255 | } | 4256 | } |
4256 | 4257 | ||
4257 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) | 4258 | static int sock_has_perm(struct sock *sk, u32 perms) |
4258 | { | 4259 | { |
4259 | struct sk_security_struct *sksec = sk->sk_security; | 4260 | struct sk_security_struct *sksec = sk->sk_security; |
4260 | struct common_audit_data ad; | 4261 | struct common_audit_data ad; |
4261 | struct lsm_network_audit net = {0,}; | 4262 | struct lsm_network_audit net = {0,}; |
4262 | u32 tsid = task_sid(task); | ||
4263 | 4263 | ||
4264 | if (sksec->sid == SECINITSID_KERNEL) | 4264 | if (sksec->sid == SECINITSID_KERNEL) |
4265 | return 0; | 4265 | return 0; |
@@ -4268,7 +4268,8 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) | |||
4268 | ad.u.net = &net; | 4268 | ad.u.net = &net; |
4269 | ad.u.net->sk = sk; | 4269 | ad.u.net->sk = sk; |
4270 | 4270 | ||
4271 | return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); | 4271 | return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms, |
4272 | &ad); | ||
4272 | } | 4273 | } |
4273 | 4274 | ||
4274 | static int selinux_socket_create(int family, int type, | 4275 | static int selinux_socket_create(int family, int type, |
@@ -4330,7 +4331,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
4330 | u16 family; | 4331 | u16 family; |
4331 | int err; | 4332 | int err; |
4332 | 4333 | ||
4333 | err = sock_has_perm(current, sk, SOCKET__BIND); | 4334 | err = sock_has_perm(sk, SOCKET__BIND); |
4334 | if (err) | 4335 | if (err) |
4335 | goto out; | 4336 | goto out; |
4336 | 4337 | ||
@@ -4365,7 +4366,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
4365 | 4366 | ||
4366 | inet_get_local_port_range(sock_net(sk), &low, &high); | 4367 | inet_get_local_port_range(sock_net(sk), &low, &high); |
4367 | 4368 | ||
4368 | if (snum < max(PROT_SOCK, low) || snum > high) { | 4369 | if (snum < max(inet_prot_sock(sock_net(sk)), low) || |
4370 | snum > high) { | ||
4369 | err = sel_netport_sid(sk->sk_protocol, | 4371 | err = sel_netport_sid(sk->sk_protocol, |
4370 | snum, &sid); | 4372 | snum, &sid); |
4371 | if (err) | 4373 | if (err) |
@@ -4429,7 +4431,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
4429 | struct sk_security_struct *sksec = sk->sk_security; | 4431 | struct sk_security_struct *sksec = sk->sk_security; |
4430 | int err; | 4432 | int err; |
4431 | 4433 | ||
4432 | err = sock_has_perm(current, sk, SOCKET__CONNECT); | 4434 | err = sock_has_perm(sk, SOCKET__CONNECT); |
4433 | if (err) | 4435 | if (err) |
4434 | return err; | 4436 | return err; |
4435 | 4437 | ||
@@ -4481,7 +4483,7 @@ out: | |||
4481 | 4483 | ||
4482 | static int selinux_socket_listen(struct socket *sock, int backlog) | 4484 | static int selinux_socket_listen(struct socket *sock, int backlog) |
4483 | { | 4485 | { |
4484 | return sock_has_perm(current, sock->sk, SOCKET__LISTEN); | 4486 | return sock_has_perm(sock->sk, SOCKET__LISTEN); |
4485 | } | 4487 | } |
4486 | 4488 | ||
4487 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | 4489 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) |
@@ -4492,7 +4494,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
4492 | u16 sclass; | 4494 | u16 sclass; |
4493 | u32 sid; | 4495 | u32 sid; |
4494 | 4496 | ||
4495 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); | 4497 | err = sock_has_perm(sock->sk, SOCKET__ACCEPT); |
4496 | if (err) | 4498 | if (err) |
4497 | return err; | 4499 | return err; |
4498 | 4500 | ||
@@ -4513,30 +4515,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
4513 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 4515 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
4514 | int size) | 4516 | int size) |
4515 | { | 4517 | { |
4516 | return sock_has_perm(current, sock->sk, SOCKET__WRITE); | 4518 | return sock_has_perm(sock->sk, SOCKET__WRITE); |
4517 | } | 4519 | } |
4518 | 4520 | ||
4519 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 4521 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
4520 | int size, int flags) | 4522 | int size, int flags) |
4521 | { | 4523 | { |
4522 | return sock_has_perm(current, sock->sk, SOCKET__READ); | 4524 | return sock_has_perm(sock->sk, SOCKET__READ); |
4523 | } | 4525 | } |
4524 | 4526 | ||
4525 | static int selinux_socket_getsockname(struct socket *sock) | 4527 | static int selinux_socket_getsockname(struct socket *sock) |
4526 | { | 4528 | { |
4527 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); | 4529 | return sock_has_perm(sock->sk, SOCKET__GETATTR); |
4528 | } | 4530 | } |
4529 | 4531 | ||
4530 | static int selinux_socket_getpeername(struct socket *sock) | 4532 | static int selinux_socket_getpeername(struct socket *sock) |
4531 | { | 4533 | { |
4532 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); | 4534 | return sock_has_perm(sock->sk, SOCKET__GETATTR); |
4533 | } | 4535 | } |
4534 | 4536 | ||
4535 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) | 4537 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) |
4536 | { | 4538 | { |
4537 | int err; | 4539 | int err; |
4538 | 4540 | ||
4539 | err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); | 4541 | err = sock_has_perm(sock->sk, SOCKET__SETOPT); |
4540 | if (err) | 4542 | if (err) |
4541 | return err; | 4543 | return err; |
4542 | 4544 | ||
@@ -4546,12 +4548,12 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname | |||
4546 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 4548 | static int selinux_socket_getsockopt(struct socket *sock, int level, |
4547 | int optname) | 4549 | int optname) |
4548 | { | 4550 | { |
4549 | return sock_has_perm(current, sock->sk, SOCKET__GETOPT); | 4551 | return sock_has_perm(sock->sk, SOCKET__GETOPT); |
4550 | } | 4552 | } |
4551 | 4553 | ||
4552 | static int selinux_socket_shutdown(struct socket *sock, int how) | 4554 | static int selinux_socket_shutdown(struct socket *sock, int how) |
4553 | { | 4555 | { |
4554 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); | 4556 | return sock_has_perm(sock->sk, SOCKET__SHUTDOWN); |
4555 | } | 4557 | } |
4556 | 4558 | ||
4557 | static int selinux_socket_unix_stream_connect(struct sock *sock, | 4559 | static int selinux_socket_unix_stream_connect(struct sock *sock, |
@@ -5039,7 +5041,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
5039 | goto out; | 5041 | goto out; |
5040 | } | 5042 | } |
5041 | 5043 | ||
5042 | err = sock_has_perm(current, sk, perm); | 5044 | err = sock_has_perm(sk, perm); |
5043 | out: | 5045 | out: |
5044 | return err; | 5046 | return err; |
5045 | } | 5047 | } |
@@ -5370,20 +5372,17 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
5370 | return selinux_nlmsg_perm(sk, skb); | 5372 | return selinux_nlmsg_perm(sk, skb); |
5371 | } | 5373 | } |
5372 | 5374 | ||
5373 | static int ipc_alloc_security(struct task_struct *task, | 5375 | static int ipc_alloc_security(struct kern_ipc_perm *perm, |
5374 | struct kern_ipc_perm *perm, | ||
5375 | u16 sclass) | 5376 | u16 sclass) |
5376 | { | 5377 | { |
5377 | struct ipc_security_struct *isec; | 5378 | struct ipc_security_struct *isec; |
5378 | u32 sid; | ||
5379 | 5379 | ||
5380 | isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); | 5380 | isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); |
5381 | if (!isec) | 5381 | if (!isec) |
5382 | return -ENOMEM; | 5382 | return -ENOMEM; |
5383 | 5383 | ||
5384 | sid = task_sid(task); | ||
5385 | isec->sclass = sclass; | 5384 | isec->sclass = sclass; |
5386 | isec->sid = sid; | 5385 | isec->sid = current_sid(); |
5387 | perm->security = isec; | 5386 | perm->security = isec; |
5388 | 5387 | ||
5389 | return 0; | 5388 | return 0; |
@@ -5451,7 +5450,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
5451 | u32 sid = current_sid(); | 5450 | u32 sid = current_sid(); |
5452 | int rc; | 5451 | int rc; |
5453 | 5452 | ||
5454 | rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ); | 5453 | rc = ipc_alloc_security(&msq->q_perm, SECCLASS_MSGQ); |
5455 | if (rc) | 5454 | if (rc) |
5456 | return rc; | 5455 | return rc; |
5457 | 5456 | ||
@@ -5498,7 +5497,8 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd) | |||
5498 | case IPC_INFO: | 5497 | case IPC_INFO: |
5499 | case MSG_INFO: | 5498 | case MSG_INFO: |
5500 | /* No specific object, just general system-wide information. */ | 5499 | /* No specific object, just general system-wide information. */ |
5501 | return task_has_system(current, SYSTEM__IPC_INFO); | 5500 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, |
5501 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); | ||
5502 | case IPC_STAT: | 5502 | case IPC_STAT: |
5503 | case MSG_STAT: | 5503 | case MSG_STAT: |
5504 | perms = MSGQ__GETATTR | MSGQ__ASSOCIATE; | 5504 | perms = MSGQ__GETATTR | MSGQ__ASSOCIATE; |
@@ -5592,7 +5592,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
5592 | u32 sid = current_sid(); | 5592 | u32 sid = current_sid(); |
5593 | int rc; | 5593 | int rc; |
5594 | 5594 | ||
5595 | rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM); | 5595 | rc = ipc_alloc_security(&shp->shm_perm, SECCLASS_SHM); |
5596 | if (rc) | 5596 | if (rc) |
5597 | return rc; | 5597 | return rc; |
5598 | 5598 | ||
@@ -5640,7 +5640,8 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd) | |||
5640 | case IPC_INFO: | 5640 | case IPC_INFO: |
5641 | case SHM_INFO: | 5641 | case SHM_INFO: |
5642 | /* No specific object, just general system-wide information. */ | 5642 | /* No specific object, just general system-wide information. */ |
5643 | return task_has_system(current, SYSTEM__IPC_INFO); | 5643 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, |
5644 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); | ||
5644 | case IPC_STAT: | 5645 | case IPC_STAT: |
5645 | case SHM_STAT: | 5646 | case SHM_STAT: |
5646 | perms = SHM__GETATTR | SHM__ASSOCIATE; | 5647 | perms = SHM__GETATTR | SHM__ASSOCIATE; |
@@ -5684,7 +5685,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
5684 | u32 sid = current_sid(); | 5685 | u32 sid = current_sid(); |
5685 | int rc; | 5686 | int rc; |
5686 | 5687 | ||
5687 | rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM); | 5688 | rc = ipc_alloc_security(&sma->sem_perm, SECCLASS_SEM); |
5688 | if (rc) | 5689 | if (rc) |
5689 | return rc; | 5690 | return rc; |
5690 | 5691 | ||
@@ -5732,7 +5733,8 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd) | |||
5732 | case IPC_INFO: | 5733 | case IPC_INFO: |
5733 | case SEM_INFO: | 5734 | case SEM_INFO: |
5734 | /* No specific object, just general system-wide information. */ | 5735 | /* No specific object, just general system-wide information. */ |
5735 | return task_has_system(current, SYSTEM__IPC_INFO); | 5736 | return avc_has_perm(current_sid(), SECINITSID_KERNEL, |
5737 | SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); | ||
5736 | case GETPID: | 5738 | case GETPID: |
5737 | case GETNCNT: | 5739 | case GETNCNT: |
5738 | case GETZCNT: | 5740 | case GETZCNT: |
@@ -5813,15 +5815,16 @@ static int selinux_getprocattr(struct task_struct *p, | |||
5813 | int error; | 5815 | int error; |
5814 | unsigned len; | 5816 | unsigned len; |
5815 | 5817 | ||
5818 | rcu_read_lock(); | ||
5819 | __tsec = __task_cred(p)->security; | ||
5820 | |||
5816 | if (current != p) { | 5821 | if (current != p) { |
5817 | error = current_has_perm(p, PROCESS__GETATTR); | 5822 | error = avc_has_perm(current_sid(), __tsec->sid, |
5823 | SECCLASS_PROCESS, PROCESS__GETATTR, NULL); | ||
5818 | if (error) | 5824 | if (error) |
5819 | return error; | 5825 | goto bad; |
5820 | } | 5826 | } |
5821 | 5827 | ||
5822 | rcu_read_lock(); | ||
5823 | __tsec = __task_cred(p)->security; | ||
5824 | |||
5825 | if (!strcmp(name, "current")) | 5828 | if (!strcmp(name, "current")) |
5826 | sid = __tsec->sid; | 5829 | sid = __tsec->sid; |
5827 | else if (!strcmp(name, "prev")) | 5830 | else if (!strcmp(name, "prev")) |
@@ -5834,8 +5837,10 @@ static int selinux_getprocattr(struct task_struct *p, | |||
5834 | sid = __tsec->keycreate_sid; | 5837 | sid = __tsec->keycreate_sid; |
5835 | else if (!strcmp(name, "sockcreate")) | 5838 | else if (!strcmp(name, "sockcreate")) |
5836 | sid = __tsec->sockcreate_sid; | 5839 | sid = __tsec->sockcreate_sid; |
5837 | else | 5840 | else { |
5838 | goto invalid; | 5841 | error = -EINVAL; |
5842 | goto bad; | ||
5843 | } | ||
5839 | rcu_read_unlock(); | 5844 | rcu_read_unlock(); |
5840 | 5845 | ||
5841 | if (!sid) | 5846 | if (!sid) |
@@ -5846,41 +5851,37 @@ static int selinux_getprocattr(struct task_struct *p, | |||
5846 | return error; | 5851 | return error; |
5847 | return len; | 5852 | return len; |
5848 | 5853 | ||
5849 | invalid: | 5854 | bad: |
5850 | rcu_read_unlock(); | 5855 | rcu_read_unlock(); |
5851 | return -EINVAL; | 5856 | return error; |
5852 | } | 5857 | } |
5853 | 5858 | ||
5854 | static int selinux_setprocattr(struct task_struct *p, | 5859 | static int selinux_setprocattr(const char *name, void *value, size_t size) |
5855 | char *name, void *value, size_t size) | ||
5856 | { | 5860 | { |
5857 | struct task_security_struct *tsec; | 5861 | struct task_security_struct *tsec; |
5858 | struct cred *new; | 5862 | struct cred *new; |
5859 | u32 sid = 0, ptsid; | 5863 | u32 mysid = current_sid(), sid = 0, ptsid; |
5860 | int error; | 5864 | int error; |
5861 | char *str = value; | 5865 | char *str = value; |
5862 | 5866 | ||
5863 | if (current != p) { | ||
5864 | /* SELinux only allows a process to change its own | ||
5865 | security attributes. */ | ||
5866 | return -EACCES; | ||
5867 | } | ||
5868 | |||
5869 | /* | 5867 | /* |
5870 | * Basic control over ability to set these attributes at all. | 5868 | * 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 | */ | 5869 | */ |
5874 | if (!strcmp(name, "exec")) | 5870 | if (!strcmp(name, "exec")) |
5875 | error = current_has_perm(p, PROCESS__SETEXEC); | 5871 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, |
5872 | PROCESS__SETEXEC, NULL); | ||
5876 | else if (!strcmp(name, "fscreate")) | 5873 | else if (!strcmp(name, "fscreate")) |
5877 | error = current_has_perm(p, PROCESS__SETFSCREATE); | 5874 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, |
5875 | PROCESS__SETFSCREATE, NULL); | ||
5878 | else if (!strcmp(name, "keycreate")) | 5876 | else if (!strcmp(name, "keycreate")) |
5879 | error = current_has_perm(p, PROCESS__SETKEYCREATE); | 5877 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, |
5878 | PROCESS__SETKEYCREATE, NULL); | ||
5880 | else if (!strcmp(name, "sockcreate")) | 5879 | else if (!strcmp(name, "sockcreate")) |
5881 | error = current_has_perm(p, PROCESS__SETSOCKCREATE); | 5880 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, |
5881 | PROCESS__SETSOCKCREATE, NULL); | ||
5882 | else if (!strcmp(name, "current")) | 5882 | else if (!strcmp(name, "current")) |
5883 | error = current_has_perm(p, PROCESS__SETCURRENT); | 5883 | error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, |
5884 | PROCESS__SETCURRENT, NULL); | ||
5884 | else | 5885 | else |
5885 | error = -EINVAL; | 5886 | error = -EINVAL; |
5886 | if (error) | 5887 | if (error) |
@@ -5934,7 +5935,8 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5934 | } else if (!strcmp(name, "fscreate")) { | 5935 | } else if (!strcmp(name, "fscreate")) { |
5935 | tsec->create_sid = sid; | 5936 | tsec->create_sid = sid; |
5936 | } else if (!strcmp(name, "keycreate")) { | 5937 | } else if (!strcmp(name, "keycreate")) { |
5937 | error = may_create_key(sid, p); | 5938 | error = avc_has_perm(mysid, sid, SECCLASS_KEY, KEY__CREATE, |
5939 | NULL); | ||
5938 | if (error) | 5940 | if (error) |
5939 | goto abort_change; | 5941 | goto abort_change; |
5940 | tsec->keycreate_sid = sid; | 5942 | tsec->keycreate_sid = sid; |
@@ -5961,7 +5963,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5961 | 5963 | ||
5962 | /* Check for ptracing, and update the task SID if ok. | 5964 | /* Check for ptracing, and update the task SID if ok. |
5963 | Otherwise, leave SID unchanged and fail. */ | 5965 | Otherwise, leave SID unchanged and fail. */ |
5964 | ptsid = ptrace_parent_sid(p); | 5966 | ptsid = ptrace_parent_sid(); |
5965 | if (ptsid != 0) { | 5967 | if (ptsid != 0) { |
5966 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, | 5968 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, |
5967 | PROCESS__PTRACE, NULL); | 5969 | PROCESS__PTRACE, NULL); |
@@ -6209,7 +6211,6 @@ static struct security_hook_list selinux_hooks[] = { | |||
6209 | LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler), | 6211 | LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler), |
6210 | LSM_HOOK_INIT(task_movememory, selinux_task_movememory), | 6212 | LSM_HOOK_INIT(task_movememory, selinux_task_movememory), |
6211 | LSM_HOOK_INIT(task_kill, selinux_task_kill), | 6213 | 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), | 6214 | LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode), |
6214 | 6215 | ||
6215 | LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission), | 6216 | LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission), |
@@ -6349,7 +6350,7 @@ static __init int selinux_init(void) | |||
6349 | 0, SLAB_PANIC, NULL); | 6350 | 0, SLAB_PANIC, NULL); |
6350 | avc_init(); | 6351 | avc_init(); |
6351 | 6352 | ||
6352 | security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks)); | 6353 | security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux"); |
6353 | 6354 | ||
6354 | if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) | 6355 | if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) |
6355 | panic("SELinux: Unable to register AVC netcache callback\n"); | 6356 | panic("SELinux: Unable to register AVC netcache callback\n"); |