summaryrefslogtreecommitdiff
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-21 12:49:56 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-21 12:49:56 -0800
commitc9341ee0af4df0af8b727873ef851227345defed (patch)
tree81a48ed068936afd58a1cb9b6cb65f6e16dcb343 /security/selinux/hooks.c
parent7a771ceac771d009f7203c40b256b0608d7ea2f8 (diff)
parent61841be6358c03e864ad4c386c9a102edbba9cb8 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security layer updates from James Morris: "Highlights: - major AppArmor update: policy namespaces & lots of fixes - add /sys/kernel/security/lsm node for easy detection of loaded LSMs - SELinux cgroupfs labeling support - SELinux context mounts on tmpfs, ramfs, devpts within user namespaces - improved TPM 2.0 support" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (117 commits) tpm: declare tpm2_get_pcr_allocation() as static tpm: Fix expected number of response bytes of TPM1.2 PCR Extend tpm xen: drop unneeded chip variable tpm: fix misspelled "facilitate" in module parameter description tpm_tis: fix the error handling of init_tis() KEYS: Use memzero_explicit() for secret data KEYS: Fix an error code in request_master_key() sign-file: fix build error in sign-file.c with libressl selinux: allow changing labels for cgroupfs selinux: fix off-by-one in setprocattr tpm: silence an array overflow warning tpm: fix the type of owned field in cap_t tpm: add securityfs support for TPM 2.0 firmware event log tpm: enhance read_log_of() to support Physical TPM event log tpm: enhance TPM 2.0 PCR extend to support multiple banks tpm: implement TPM 2.0 capability to get active PCR banks tpm: fix RC value check in tpm2_seal_trusted tpm_tis: fix iTPM probe via probe_itpm() function tpm: Begin the process to deprecate user_read_timer tpm: remove tpm_read_index and tpm_write_index from tpm.h ...
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c381
1 files changed, 189 insertions, 192 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d98550abe16d..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)
return sid;
}
-/*
- * get the subjective security ID of the current task
- */
-static inline u32 current_sid(void)
-{
- const struct task_security_struct *tsec = current_security();
-
- return tsec->sid;
-}
-
/* Allocate and free functions for each kind of security blob. */
static int inode_alloc_security(struct inode *inode)
@@ -490,8 +480,11 @@ static int selinux_is_sblabel_mnt(struct super_block *sb)
sbsec->behavior == SECURITY_FS_USE_NATIVE ||
/* Special handling. Genfs but also in-core setxattr handler */
!strcmp(sb->s_type->name, "sysfs") ||
+ !strcmp(sb->s_type->name, "cgroup") ||
+ !strcmp(sb->s_type->name, "cgroup2") ||
!strcmp(sb->s_type->name, "pstore") ||
!strcmp(sb->s_type->name, "debugfs") ||
+ !strcmp(sb->s_type->name, "tracefs") ||
!strcmp(sb->s_type->name, "rootfs");
}
@@ -833,10 +826,14 @@ static int selinux_set_mnt_opts(struct super_block *sb,
}
/*
- * If this is a user namespace mount, no contexts are allowed
- * on the command line and security labels must be ignored.
+ * If this is a user namespace mount and the filesystem type is not
+ * explicitly whitelisted, then no contexts are allowed on the command
+ * line and security labels must be ignored.
*/
- if (sb->s_user_ns != &init_user_ns) {
+ if (sb->s_user_ns != &init_user_ns &&
+ strcmp(sb->s_type->name, "tmpfs") &&
+ strcmp(sb->s_type->name, "ramfs") &&
+ strcmp(sb->s_type->name, "devpts")) {
if (context_sid || fscontext_sid || rootcontext_sid ||
defcontext_sid) {
rc = -EACCES;
@@ -1268,6 +1265,8 @@ static inline int default_protocol_dgram(int protocol)
static inline u16 socket_type_to_security_class(int family, int type, int protocol)
{
+ int extsockclass = selinux_policycap_extsockclass;
+
switch (family) {
case PF_UNIX:
switch (type) {
@@ -1282,13 +1281,19 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
case PF_INET6:
switch (type) {
case SOCK_STREAM:
+ case SOCK_SEQPACKET:
if (default_protocol_stream(protocol))
return SECCLASS_TCP_SOCKET;
+ else if (extsockclass && protocol == IPPROTO_SCTP)
+ return SECCLASS_SCTP_SOCKET;
else
return SECCLASS_RAWIP_SOCKET;
case SOCK_DGRAM:
if (default_protocol_dgram(protocol))
return SECCLASS_UDP_SOCKET;
+ else if (extsockclass && (protocol == IPPROTO_ICMP ||
+ protocol == IPPROTO_ICMPV6))
+ return SECCLASS_ICMP_SOCKET;
else
return SECCLASS_RAWIP_SOCKET;
case SOCK_DCCP:
@@ -1342,6 +1347,66 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
return SECCLASS_APPLETALK_SOCKET;
}
+ if (extsockclass) {
+ switch (family) {
+ case PF_AX25:
+ return SECCLASS_AX25_SOCKET;
+ case PF_IPX:
+ return SECCLASS_IPX_SOCKET;
+ case PF_NETROM:
+ return SECCLASS_NETROM_SOCKET;
+ case PF_ATMPVC:
+ return SECCLASS_ATMPVC_SOCKET;
+ case PF_X25:
+ return SECCLASS_X25_SOCKET;
+ case PF_ROSE:
+ return SECCLASS_ROSE_SOCKET;
+ case PF_DECnet:
+ return SECCLASS_DECNET_SOCKET;
+ case PF_ATMSVC:
+ return SECCLASS_ATMSVC_SOCKET;
+ case PF_RDS:
+ return SECCLASS_RDS_SOCKET;
+ case PF_IRDA:
+ return SECCLASS_IRDA_SOCKET;
+ case PF_PPPOX:
+ return SECCLASS_PPPOX_SOCKET;
+ case PF_LLC:
+ return SECCLASS_LLC_SOCKET;
+ case PF_CAN:
+ return SECCLASS_CAN_SOCKET;
+ case PF_TIPC:
+ return SECCLASS_TIPC_SOCKET;
+ case PF_BLUETOOTH:
+ return SECCLASS_BLUETOOTH_SOCKET;
+ case PF_IUCV:
+ return SECCLASS_IUCV_SOCKET;
+ case PF_RXRPC:
+ return SECCLASS_RXRPC_SOCKET;
+ case PF_ISDN:
+ return SECCLASS_ISDN_SOCKET;
+ case PF_PHONET:
+ return SECCLASS_PHONET_SOCKET;
+ case PF_IEEE802154:
+ return SECCLASS_IEEE802154_SOCKET;
+ case PF_CAIF:
+ return SECCLASS_CAIF_SOCKET;
+ case PF_ALG:
+ return SECCLASS_ALG_SOCKET;
+ case PF_NFC:
+ return SECCLASS_NFC_SOCKET;
+ case PF_VSOCK:
+ return SECCLASS_VSOCK_SOCKET;
+ case PF_KCM:
+ return SECCLASS_KCM_SOCKET;
+ case PF_QIPCRTR:
+ return SECCLASS_QIPCRTR_SOCKET;
+#if PF_MAX > 43
+#error New address family defined, please update this function.
+#endif
+ }
+ }
+
return SECCLASS_SOCKET;
}
@@ -1608,55 +1673,6 @@ static inline u32 signal_to_av(int sig)
return perm;
}
-/*
- * Check permission between a pair of credentials
- * fork check, ptrace check, etc.
- */
-static int cred_has_perm(const struct cred *actor,
- const struct cred *target,
- u32 perms)
-{
- u32 asid = cred_sid(actor), tsid = cred_sid(target);
-
- return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
-}
-
-/*
- * Check permission between a pair of tasks, e.g. signal checks,
- * fork check, ptrace check, etc.
- * tsk1 is the actor and tsk2 is the target
- * - this uses the default subjective creds of tsk1
- */
-static int task_has_perm(const struct task_struct *tsk1,
- const struct task_struct *tsk2,
- u32 perms)
-{
- const struct task_security_struct *__tsec1, *__tsec2;
- u32 sid1, sid2;
-
- rcu_read_lock();
- __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
- __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
- rcu_read_unlock();
- return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
-}
-
-/*
- * Check permission between current and another task, e.g. signal checks,
- * fork check, ptrace check, etc.
- * current is the actor and tsk2 is the target
- * - this uses current's subjective creds
- */
-static int current_has_perm(const struct task_struct *tsk,
- u32 perms)
-{
- u32 sid, tsid;
-
- sid = current_sid();
- tsid = task_sid(tsk);
- return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
-}
-
#if CAP_LAST_CAP > 63
#error Fix SELinux to handle capabilities > 63.
#endif
@@ -1698,16 +1714,6 @@ static int cred_has_capability(const struct cred *cred,
return rc;
}
-/* Check whether a task is allowed to use a system operation. */
-static int task_has_system(struct task_struct *tsk,
- u32 perms)
-{
- u32 sid = task_sid(tsk);
-
- return avc_has_perm(sid, SECINITSID_KERNEL,
- SECCLASS_SYSTEM, perms, NULL);
-}
-
/* Check whether a task has a particular permission to an inode.
The 'adp' parameter is optional and allows other audit
data to be passed (e.g. the dentry). */
@@ -1879,15 +1885,6 @@ static int may_create(struct inode *dir,
FILESYSTEM__ASSOCIATE, &ad);
}
-/* Check whether a task can create a key. */
-static int may_create_key(u32 ksid,
- struct task_struct *ctx)
-{
- u32 sid = task_sid(ctx);
-
- return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
-}
-
#define MAY_LINK 0
#define MAY_UNLINK 1
#define MAY_RMDIR 2
@@ -2143,24 +2140,26 @@ static int selinux_binder_transfer_file(struct task_struct *from,
static int selinux_ptrace_access_check(struct task_struct *child,
unsigned int mode)
{
- if (mode & PTRACE_MODE_READ) {
- u32 sid = current_sid();
- u32 csid = task_sid(child);
+ u32 sid = current_sid();
+ u32 csid = task_sid(child);
+
+ if (mode & PTRACE_MODE_READ)
return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
- }
- return current_has_perm(child, PROCESS__PTRACE);
+ return avc_has_perm(sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
}
static int selinux_ptrace_traceme(struct task_struct *parent)
{
- return task_has_perm(parent, current, PROCESS__PTRACE);
+ return avc_has_perm(task_sid(parent), current_sid(), SECCLASS_PROCESS,
+ PROCESS__PTRACE, NULL);
}
static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
kernel_cap_t *inheritable, kernel_cap_t *permitted)
{
- return current_has_perm(target, PROCESS__GETCAP);
+ return avc_has_perm(current_sid(), task_sid(target), SECCLASS_PROCESS,
+ PROCESS__GETCAP, NULL);
}
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,
const kernel_cap_t *inheritable,
const kernel_cap_t *permitted)
{
- return cred_has_perm(old, new, PROCESS__SETCAP);
+ return avc_has_perm(cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
+ PROCESS__SETCAP, NULL);
}
/*
@@ -2224,29 +2224,22 @@ static int selinux_quota_on(struct dentry *dentry)
static int selinux_syslog(int type)
{
- int rc;
-
switch (type) {
case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
- rc = task_has_system(current, SYSTEM__SYSLOG_READ);
- break;
+ return avc_has_perm(current_sid(), SECINITSID_KERNEL,
+ SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);
case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
/* Set level of messages printed to console */
case SYSLOG_ACTION_CONSOLE_LEVEL:
- rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
- break;
- case SYSLOG_ACTION_CLOSE: /* Close log */
- case SYSLOG_ACTION_OPEN: /* Open log */
- case SYSLOG_ACTION_READ: /* Read from log */
- case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
- case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
- default:
- rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
- break;
+ return avc_has_perm(current_sid(), SECINITSID_KERNEL,
+ SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,
+ NULL);
}
- return rc;
+ /* All other syslog types */
+ return avc_has_perm(current_sid(), SECINITSID_KERNEL,
+ SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);
}
/*
@@ -2271,13 +2264,13 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
/* binprm security operations */
-static u32 ptrace_parent_sid(struct task_struct *task)
+static u32 ptrace_parent_sid(void)
{
u32 sid = 0;
struct task_struct *tracer;
rcu_read_lock();
- tracer = ptrace_parent(task);
+ tracer = ptrace_parent(current);
if (tracer)
sid = task_sid(tracer);
rcu_read_unlock();
@@ -2406,7 +2399,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
* changes its SID has the appropriate permit */
if (bprm->unsafe &
(LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
- u32 ptsid = ptrace_parent_sid(current);
+ u32 ptsid = ptrace_parent_sid();
if (ptsid != 0) {
rc = avc_has_perm(ptsid, new_tsec->sid,
SECCLASS_PROCESS,
@@ -3503,6 +3496,7 @@ static int default_noexec;
static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
{
const struct cred *cred = current_cred();
+ u32 sid = cred_sid(cred);
int rc = 0;
if (default_noexec &&
@@ -3513,7 +3507,8 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
* private file mapping that will also be writable.
* This has an additional check.
*/
- rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
+ rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
+ PROCESS__EXECMEM, NULL);
if (rc)
goto error;
}
@@ -3564,6 +3559,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
unsigned long prot)
{
const struct cred *cred = current_cred();
+ u32 sid = cred_sid(cred);
if (selinux_checkreqprot)
prot = reqprot;
@@ -3573,12 +3569,14 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
int rc = 0;
if (vma->vm_start >= vma->vm_mm->start_brk &&
vma->vm_end <= vma->vm_mm->brk) {
- rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
+ rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
+ PROCESS__EXECHEAP, NULL);
} else if (!vma->vm_file &&
((vma->vm_start <= vma->vm_mm->start_stack &&
vma->vm_end >= vma->vm_mm->start_stack) ||
vma_is_stack_for_current(vma))) {
- rc = current_has_perm(current, PROCESS__EXECSTACK);
+ rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
+ PROCESS__EXECSTACK, NULL);
} else if (vma->vm_file && vma->anon_vma) {
/*
* 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)
static int selinux_task_create(unsigned long clone_flags)
{
- return current_has_perm(current, PROCESS__FORK);
+ u32 sid = current_sid();
+
+ return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
}
/*
@@ -3821,15 +3821,12 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
static int selinux_kernel_module_request(char *kmod_name)
{
- u32 sid;
struct common_audit_data ad;
- sid = task_sid(current);
-
ad.type = LSM_AUDIT_DATA_KMOD;
ad.u.kmod_name = kmod_name;
- return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
+ return avc_has_perm(current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
SYSTEM__MODULE_REQUEST, &ad);
}
@@ -3881,17 +3878,20 @@ static int selinux_kernel_read_file(struct file *file,
static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
{
- return current_has_perm(p, PROCESS__SETPGID);
+ return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
+ PROCESS__SETPGID, NULL);
}
static int selinux_task_getpgid(struct task_struct *p)
{
- return current_has_perm(p, PROCESS__GETPGID);
+ return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
+ PROCESS__GETPGID, NULL);
}
static int selinux_task_getsid(struct task_struct *p)
{
- return current_has_perm(p, PROCESS__GETSESSION);
+ return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
+ PROCESS__GETSESSION, NULL);
}
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)
static int selinux_task_setnice(struct task_struct *p, int nice)
{
- return current_has_perm(p, PROCESS__SETSCHED);
+ return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
+ PROCESS__SETSCHED, NULL);
}
static int selinux_task_setioprio(struct task_struct *p, int ioprio)
{
- return current_has_perm(p, PROCESS__SETSCHED);
+ return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
+ PROCESS__SETSCHED, NULL);
}
static int selinux_task_getioprio(struct task_struct *p)
{
- return current_has_perm(p, PROCESS__GETSCHED);
+ return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
+ PROCESS__GETSCHED, NULL);
}
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,
later be used as a safe reset point for the soft limit
upon context transitions. See selinux_bprm_committing_creds. */
if (old_rlim->rlim_max != new_rlim->rlim_max)
- return current_has_perm(p, PROCESS__SETRLIMIT);
+ return avc_has_perm(current_sid(), task_sid(p),
+ SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
return 0;
}
static int selinux_task_setscheduler(struct task_struct *p)
{
- return current_has_perm(p, PROCESS__SETSCHED);
+ return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
+ PROCESS__SETSCHED, NULL);
}
static int selinux_task_getscheduler(struct task_struct *p)
{
- return current_has_perm(p, PROCESS__GETSCHED);
+ return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
+ PROCESS__GETSCHED, NULL);
}
static int selinux_task_movememory(struct task_struct *p)
{
- return current_has_perm(p, PROCESS__SETSCHED);
+ return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
+ PROCESS__SETSCHED, NULL);
}
static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
int sig, u32 secid)
{
u32 perm;
- int rc;
if (!sig)
perm = PROCESS__SIGNULL; /* null signal; existence test */
else
perm = signal_to_av(sig);
- if (secid)
- rc = avc_has_perm(secid, task_sid(p),
- SECCLASS_PROCESS, perm, NULL);
- else
- rc = current_has_perm(p, perm);
- return rc;
-}
-
-static int selinux_task_wait(struct task_struct *p)
-{
- return task_has_perm(p, current, PROCESS__SIGCHLD);
+ if (!secid)
+ secid = current_sid();
+ return avc_has_perm(secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);
}
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,
socksid);
}
-static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
+static int sock_has_perm(struct sock *sk, u32 perms)
{
struct sk_security_struct *sksec = sk->sk_security;
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
- u32 tsid = task_sid(task);
if (sksec->sid == SECINITSID_KERNEL)
return 0;
@@ -4268,7 +4265,8 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
ad.u.net = &net;
ad.u.net->sk = sk;
- return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
+ return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms,
+ &ad);
}
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
u16 family;
int err;
- err = sock_has_perm(current, sk, SOCKET__BIND);
+ err = sock_has_perm(sk, SOCKET__BIND);
if (err)
goto out;
@@ -4429,7 +4427,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
struct sk_security_struct *sksec = sk->sk_security;
int err;
- err = sock_has_perm(current, sk, SOCKET__CONNECT);
+ err = sock_has_perm(sk, SOCKET__CONNECT);
if (err)
return err;
@@ -4481,7 +4479,7 @@ out:
static int selinux_socket_listen(struct socket *sock, int backlog)
{
- return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
+ return sock_has_perm(sock->sk, SOCKET__LISTEN);
}
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)
u16 sclass;
u32 sid;
- err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
+ err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
if (err)
return err;
@@ -4513,30 +4511,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
int size)
{
- return sock_has_perm(current, sock->sk, SOCKET__WRITE);
+ return sock_has_perm(sock->sk, SOCKET__WRITE);
}
static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
int size, int flags)
{
- return sock_has_perm(current, sock->sk, SOCKET__READ);
+ return sock_has_perm(sock->sk, SOCKET__READ);
}
static int selinux_socket_getsockname(struct socket *sock)
{
- return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
+ return sock_has_perm(sock->sk, SOCKET__GETATTR);
}
static int selinux_socket_getpeername(struct socket *sock)
{
- return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
+ return sock_has_perm(sock->sk, SOCKET__GETATTR);
}
static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
{
int err;
- err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
+ err = sock_has_perm(sock->sk, SOCKET__SETOPT);
if (err)
return err;
@@ -4546,12 +4544,12 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
static int selinux_socket_getsockopt(struct socket *sock, int level,
int optname)
{
- return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
+ return sock_has_perm(sock->sk, SOCKET__GETOPT);
}
static int selinux_socket_shutdown(struct socket *sock, int how)
{
- return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
+ return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
}
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)
goto out;
}
- err = sock_has_perm(current, sk, perm);
+ err = sock_has_perm(sk, perm);
out:
return err;
}
@@ -5370,20 +5368,17 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
return selinux_nlmsg_perm(sk, skb);
}
-static int ipc_alloc_security(struct task_struct *task,
- struct kern_ipc_perm *perm,
+static int ipc_alloc_security(struct kern_ipc_perm *perm,
u16 sclass)
{
struct ipc_security_struct *isec;
- u32 sid;
isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
if (!isec)
return -ENOMEM;
- sid = task_sid(task);
isec->sclass = sclass;
- isec->sid = sid;
+ isec->sid = current_sid();
perm->security = isec;
return 0;
@@ -5451,7 +5446,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
u32 sid = current_sid();
int rc;
- rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
+ rc = ipc_alloc_security(&msq->q_perm, SECCLASS_MSGQ);
if (rc)
return rc;
@@ -5498,7 +5493,8 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
case IPC_INFO:
case MSG_INFO:
/* No specific object, just general system-wide information. */
- return task_has_system(current, SYSTEM__IPC_INFO);
+ return avc_has_perm(current_sid(), SECINITSID_KERNEL,
+ SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
case IPC_STAT:
case MSG_STAT:
perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
@@ -5592,7 +5588,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
u32 sid = current_sid();
int rc;
- rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
+ rc = ipc_alloc_security(&shp->shm_perm, SECCLASS_SHM);
if (rc)
return rc;
@@ -5640,7 +5636,8 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
case IPC_INFO:
case SHM_INFO:
/* No specific object, just general system-wide information. */
- return task_has_system(current, SYSTEM__IPC_INFO);
+ return avc_has_perm(current_sid(), SECINITSID_KERNEL,
+ SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
case IPC_STAT:
case SHM_STAT:
perms = SHM__GETATTR | SHM__ASSOCIATE;
@@ -5684,7 +5681,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
u32 sid = current_sid();
int rc;
- rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
+ rc = ipc_alloc_security(&sma->sem_perm, SECCLASS_SEM);
if (rc)
return rc;
@@ -5732,7 +5729,8 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd)
case IPC_INFO:
case SEM_INFO:
/* No specific object, just general system-wide information. */
- return task_has_system(current, SYSTEM__IPC_INFO);
+ return avc_has_perm(current_sid(), SECINITSID_KERNEL,
+ SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
case GETPID:
case GETNCNT:
case GETZCNT:
@@ -5813,15 +5811,16 @@ static int selinux_getprocattr(struct task_struct *p,
int error;
unsigned len;
+ rcu_read_lock();
+ __tsec = __task_cred(p)->security;
+
if (current != p) {
- error = current_has_perm(p, PROCESS__GETATTR);
+ error = avc_has_perm(current_sid(), __tsec->sid,
+ SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
if (error)
- return error;
+ goto bad;
}
- rcu_read_lock();
- __tsec = __task_cred(p)->security;
-
if (!strcmp(name, "current"))
sid = __tsec->sid;
else if (!strcmp(name, "prev"))
@@ -5834,8 +5833,10 @@ static int selinux_getprocattr(struct task_struct *p,
sid = __tsec->keycreate_sid;
else if (!strcmp(name, "sockcreate"))
sid = __tsec->sockcreate_sid;
- else
- goto invalid;
+ else {
+ error = -EINVAL;
+ goto bad;
+ }
rcu_read_unlock();
if (!sid)
@@ -5846,41 +5847,37 @@ static int selinux_getprocattr(struct task_struct *p,
return error;
return len;
-invalid:
+bad:
rcu_read_unlock();
- return -EINVAL;
+ return error;
}
-static int selinux_setprocattr(struct task_struct *p,
- char *name, void *value, size_t size)
+static int selinux_setprocattr(const char *name, void *value, size_t size)
{
struct task_security_struct *tsec;
struct cred *new;
- u32 sid = 0, ptsid;
+ u32 mysid = current_sid(), sid = 0, ptsid;
int error;
char *str = value;
- if (current != p) {
- /* SELinux only allows a process to change its own
- security attributes. */
- return -EACCES;
- }
-
/*
* Basic control over ability to set these attributes at all.
- * current == p, but we'll pass them separately in case the
- * above restriction is ever removed.
*/
if (!strcmp(name, "exec"))
- error = current_has_perm(p, PROCESS__SETEXEC);
+ error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
+ PROCESS__SETEXEC, NULL);
else if (!strcmp(name, "fscreate"))
- error = current_has_perm(p, PROCESS__SETFSCREATE);
+ error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
+ PROCESS__SETFSCREATE, NULL);
else if (!strcmp(name, "keycreate"))
- error = current_has_perm(p, PROCESS__SETKEYCREATE);
+ error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
+ PROCESS__SETKEYCREATE, NULL);
else if (!strcmp(name, "sockcreate"))
- error = current_has_perm(p, PROCESS__SETSOCKCREATE);
+ error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
+ PROCESS__SETSOCKCREATE, NULL);
else if (!strcmp(name, "current"))
- error = current_has_perm(p, PROCESS__SETCURRENT);
+ error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
+ PROCESS__SETCURRENT, NULL);
else
error = -EINVAL;
if (error)
@@ -5934,7 +5931,8 @@ static int selinux_setprocattr(struct task_struct *p,
} else if (!strcmp(name, "fscreate")) {
tsec->create_sid = sid;
} else if (!strcmp(name, "keycreate")) {
- error = may_create_key(sid, p);
+ error = avc_has_perm(mysid, sid, SECCLASS_KEY, KEY__CREATE,
+ NULL);
if (error)
goto abort_change;
tsec->keycreate_sid = sid;
@@ -5961,7 +5959,7 @@ static int selinux_setprocattr(struct task_struct *p,
/* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and fail. */
- ptsid = ptrace_parent_sid(p);
+ ptsid = ptrace_parent_sid();
if (ptsid != 0) {
error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
PROCESS__PTRACE, NULL);
@@ -6209,7 +6207,6 @@ static struct security_hook_list selinux_hooks[] = {
LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
LSM_HOOK_INIT(task_kill, selinux_task_kill),
- LSM_HOOK_INIT(task_wait, selinux_task_wait),
LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
@@ -6349,7 +6346,7 @@ static __init int selinux_init(void)
0, SLAB_PANIC, NULL);
avc_init();
- security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
+ security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
panic("SELinux: Unable to register AVC netcache callback\n");