static LIST_HEAD(superblock_security_head);
static DEFINE_SPINLOCK(sb_security_lock);
+/* Return security context for a given sid or just the context
+ length if the buffer is null or length is 0 */
+static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
+{
+ char *context;
+ unsigned len;
+ int rc;
+
+ rc = security_sid_to_context(sid, &context, &len);
+ if (rc)
+ return rc;
+
+ if (!buffer || !size)
+ goto getsecurity_exit;
+
+ if (size < len) {
+ len = -ERANGE;
+ goto getsecurity_exit;
+ }
+ memcpy(buffer, context, len);
+
+getsecurity_exit:
+ kfree(context);
+ return len;
+}
+
/* Allocate and free functions for each kind of security blob. */
static int task_alloc_security(struct task_struct *task)
if (!tsec)
return -ENOMEM;
- tsec->magic = SELINUX_MAGIC;
tsec->task = task;
tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
task->security = tsec;
static void task_free_security(struct task_struct *task)
{
struct task_security_struct *tsec = task->security;
-
- if (!tsec || tsec->magic != SELINUX_MAGIC)
- return;
-
task->security = NULL;
kfree(tsec);
}
init_MUTEX(&isec->sem);
INIT_LIST_HEAD(&isec->list);
- isec->magic = SELINUX_MAGIC;
isec->inode = inode;
isec->sid = SECINITSID_UNLABELED;
isec->sclass = SECCLASS_FILE;
- if (tsec && tsec->magic == SELINUX_MAGIC)
- isec->task_sid = tsec->sid;
- else
- isec->task_sid = SECINITSID_UNLABELED;
+ isec->task_sid = tsec->sid;
inode->i_security = isec;
return 0;
struct inode_security_struct *isec = inode->i_security;
struct superblock_security_struct *sbsec = inode->i_sb->s_security;
- if (!isec || isec->magic != SELINUX_MAGIC)
- return;
-
spin_lock(&sbsec->isec_lock);
if (!list_empty(&isec->list))
list_del_init(&isec->list);
struct task_security_struct *tsec = current->security;
struct file_security_struct *fsec;
- fsec = kzalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
+ fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
if (!fsec)
return -ENOMEM;
- fsec->magic = SELINUX_MAGIC;
fsec->file = file;
- if (tsec && tsec->magic == SELINUX_MAGIC) {
- fsec->sid = tsec->sid;
- fsec->fown_sid = tsec->sid;
- } else {
- fsec->sid = SECINITSID_UNLABELED;
- fsec->fown_sid = SECINITSID_UNLABELED;
- }
+ fsec->sid = tsec->sid;
+ fsec->fown_sid = tsec->sid;
file->f_security = fsec;
return 0;
static void file_free_security(struct file *file)
{
struct file_security_struct *fsec = file->f_security;
-
- if (!fsec || fsec->magic != SELINUX_MAGIC)
- return;
-
file->f_security = NULL;
kfree(fsec);
}
INIT_LIST_HEAD(&sbsec->list);
INIT_LIST_HEAD(&sbsec->isec_head);
spin_lock_init(&sbsec->isec_lock);
- sbsec->magic = SELINUX_MAGIC;
sbsec->sb = sb;
sbsec->sid = SECINITSID_UNLABELED;
sbsec->def_sid = SECINITSID_FILE;
{
struct superblock_security_struct *sbsec = sb->s_security;
- if (!sbsec || sbsec->magic != SELINUX_MAGIC)
- return;
-
spin_lock(&sb_security_lock);
if (!list_empty(&sbsec->list))
list_del_init(&sbsec->list);
kfree(sbsec);
}
-#ifdef CONFIG_SECURITY_NETWORK
static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
{
struct sk_security_struct *ssec;
if (!ssec)
return -ENOMEM;
- ssec->magic = SELINUX_MAGIC;
ssec->sk = sk;
ssec->peer_sid = SECINITSID_UNLABELED;
sk->sk_security = ssec;
{
struct sk_security_struct *ssec = sk->sk_security;
- if (sk->sk_family != PF_UNIX || ssec->magic != SELINUX_MAGIC)
+ if (sk->sk_family != PF_UNIX)
return;
sk->sk_security = NULL;
kfree(ssec);
}
-#endif /* CONFIG_SECURITY_NETWORK */
/* The security server must be initialized before
any labeling or access decisions can be provided. */
has the same SID as the process. If av is zero, then
access to the file is not checked, e.g. for cases
where only the descriptor is affected like seek. */
-static inline int file_has_perm(struct task_struct *tsk,
+static int file_has_perm(struct task_struct *tsk,
struct file *file,
u32 av)
{
rc = task_has_perm(parent, child, PROCESS__PTRACE);
/* Save the SID of the tracing process for later use in apply_creds. */
- if (!rc)
+ if (!(child->ptrace & PT_PTRACED) && !rc)
csec->ptrace_sid = psec->sid;
return rc;
}
if (!bsec)
return -ENOMEM;
- bsec->magic = SELINUX_MAGIC;
bsec->bprm = bprm;
bsec->sid = SECINITSID_UNLABELED;
bsec->set = 0;
return -EACCES;
}
+static const char *selinux_inode_xattr_getsuffix(void)
+{
+ return XATTR_SELINUX_SUFFIX;
+}
+
/*
* Copy the in-core inode security context value to the user. If the
* getxattr() prior to this succeeded, check to see if we need to
*
* Permission check is handled by selinux_inode_getxattr hook.
*/
-static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
{
struct inode_security_struct *isec = inode->i_security;
- char *context;
- unsigned len;
- int rc;
- if (strcmp(name, XATTR_SELINUX_SUFFIX)) {
- rc = -EOPNOTSUPP;
- goto out;
- }
-
- rc = security_sid_to_context(isec->sid, &context, &len);
- if (rc)
- goto out;
-
- /* Probe for required buffer size */
- if (!buffer || !size) {
- rc = len;
- goto out_free;
- }
-
- if (size < len) {
- rc = -ERANGE;
- goto out_free;
- }
+ if (strcmp(name, XATTR_SELINUX_SUFFIX))
+ return -EOPNOTSUPP;
- if (err > 0) {
- if ((len == err) && !(memcmp(context, buffer, len))) {
- /* Don't need to canonicalize value */
- rc = err;
- goto out_free;
- }
- memset(buffer, 0, size);
- }
- memcpy(buffer, context, len);
- rc = len;
-out_free:
- kfree(context);
-out:
- return rc;
+ return selinux_getsecurity(isec->sid, buffer, size);
}
static int selinux_inode_setsecurity(struct inode *inode, const char *name,
prot = reqprot;
#ifndef CONFIG_PPC32
- if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXECUTABLE) &&
- (vma->vm_start >= vma->vm_mm->start_brk &&
- vma->vm_end <= vma->vm_mm->brk)) {
- /*
- * We are making an executable mapping in the brk region.
- * This has an additional execheap check.
- */
- rc = task_has_perm(current, current, PROCESS__EXECHEAP);
- if (rc)
- return rc;
- }
- if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) {
- /*
- * We are making executable a file mapping that has
- * had some COW done. Since pages might have been written,
- * check ability to execute the possibly modified content.
- * This typically should only occur for text relocations.
- */
- int rc = file_has_perm(current, vma->vm_file, FILE__EXECMOD);
- if (rc)
- return rc;
- }
- if (!vma->vm_file && (prot & PROT_EXEC) &&
- vma->vm_start <= vma->vm_mm->start_stack &&
- vma->vm_end >= vma->vm_mm->start_stack) {
- /* Attempt to make the process stack executable.
- * This has an additional execstack check.
- */
- rc = task_has_perm(current, current, PROCESS__EXECSTACK);
+ if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
+ rc = 0;
+ if (vma->vm_start >= vma->vm_mm->start_brk &&
+ vma->vm_end <= vma->vm_mm->brk) {
+ rc = task_has_perm(current, current,
+ PROCESS__EXECHEAP);
+ } else if (!vma->vm_file &&
+ vma->vm_start <= vma->vm_mm->start_stack &&
+ vma->vm_end >= vma->vm_mm->start_stack) {
+ rc = task_has_perm(current, current, PROCESS__EXECSTACK);
+ } else if (vma->vm_file && vma->anon_vma) {
+ /*
+ * We are making executable a file mapping that has
+ * had some COW done. Since pages might have been
+ * written, check ability to execute the possibly
+ * modified content. This typically should only
+ * occur for text relocations.
+ */
+ rc = file_has_perm(current, vma->vm_file,
+ FILE__EXECMOD);
+ }
if (rc)
return rc;
}
return;
}
-#ifdef CONFIG_SECURITY_NETWORK
-
/* Returns error only if unable to parse addresses */
static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad)
{
#endif /* CONFIG_NETFILTER */
-#else
-
-static inline int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
-{
- return 0;
-}
-
-#endif /* CONFIG_SECURITY_NETWORK */
-
static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
{
struct task_security_struct *tsec;
if (!isec)
return -ENOMEM;
- isec->magic = SELINUX_MAGIC;
isec->sclass = sclass;
isec->ipc_perm = perm;
- if (tsec) {
- isec->sid = tsec->sid;
- } else {
- isec->sid = SECINITSID_UNLABELED;
- }
+ isec->sid = tsec->sid;
perm->security = isec;
return 0;
static void ipc_free_security(struct kern_ipc_perm *perm)
{
struct ipc_security_struct *isec = perm->security;
- if (!isec || isec->magic != SELINUX_MAGIC)
- return;
-
perm->security = NULL;
kfree(isec);
}
if (!msec)
return -ENOMEM;
- msec->magic = SELINUX_MAGIC;
msec->msg = msg;
msec->sid = SECINITSID_UNLABELED;
msg->security = msec;
static void msg_msg_free_security(struct msg_msg *msg)
{
struct msg_security_struct *msec = msg->security;
- if (!msec || msec->magic != SELINUX_MAGIC)
- return;
msg->security = NULL;
kfree(msec);
return ipc_has_perm(ipcp, av);
}
+static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+ struct ipc_security_struct *isec = ipcp->security;
+
+ return selinux_getsecurity(isec->sid, buffer, size);
+}
+
/* module stacking operations */
static int selinux_register_security (const char *name, struct security_operations *ops)
{
char *name, void *value, size_t size)
{
struct task_security_struct *tsec;
- u32 sid, len;
- char *context;
+ u32 sid;
int error;
if (current != p) {
return error;
}
- if (!size)
- return -ERANGE;
-
tsec = p->security;
if (!strcmp(name, "current"))
if (!sid)
return 0;
- error = security_sid_to_context(sid, &context, &len);
- if (error)
- return error;
- if (len > size) {
- kfree(context);
- return -ERANGE;
- }
- memcpy(value, context, len);
- kfree(context);
- return len;
+ return selinux_getsecurity(sid, value, size);
}
static int selinux_setprocattr(struct task_struct *p,
.inode_getxattr = selinux_inode_getxattr,
.inode_listxattr = selinux_inode_listxattr,
.inode_removexattr = selinux_inode_removexattr,
+ .inode_xattr_getsuffix = selinux_inode_xattr_getsuffix,
.inode_getsecurity = selinux_inode_getsecurity,
.inode_setsecurity = selinux_inode_setsecurity,
.inode_listsecurity = selinux_inode_listsecurity,
.task_to_inode = selinux_task_to_inode,
.ipc_permission = selinux_ipc_permission,
+ .ipc_getsecurity = selinux_ipc_getsecurity,
.msg_msg_alloc_security = selinux_msg_msg_alloc_security,
.msg_msg_free_security = selinux_msg_msg_free_security,
.getprocattr = selinux_getprocattr,
.setprocattr = selinux_setprocattr,
-#ifdef CONFIG_SECURITY_NETWORK
.unix_stream_connect = selinux_socket_unix_stream_connect,
.unix_may_send = selinux_socket_unix_may_send,
.sk_alloc_security = selinux_sk_alloc_security,
.sk_free_security = selinux_sk_free_security,
.sk_getsid = selinux_sk_getsid_security,
-#endif
#ifdef CONFIG_SECURITY_NETWORK_XFRM
.xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
all processes and objects when they are created. */
security_initcall(selinux_init);
-#if defined(CONFIG_SECURITY_NETWORK) && defined(CONFIG_NETFILTER)
+#if defined(CONFIG_NETFILTER)
static struct nf_hook_ops selinux_ipv4_op = {
.hook = selinux_ipv4_postroute_last,
}
#endif
-#else /* CONFIG_SECURITY_NETWORK && CONFIG_NETFILTER */
+#else /* CONFIG_NETFILTER */
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
#define selinux_nf_ip_exit()
#endif
-#endif /* CONFIG_SECURITY_NETWORK && CONFIG_NETFILTER */
+#endif /* CONFIG_NETFILTER */
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
int selinux_disable(void)