return 1;
}
__setup("selinux=", selinux_enabled_setup);
-#else
-int selinux_enabled = 1;
#endif
/* Original (dummy) security module. */
static LIST_HEAD(superblock_security_head);
static DEFINE_SPINLOCK(sb_security_lock);
-static kmem_cache_t *sel_inode_cache;
-
-/* 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)
struct task_security_struct *tsec = current->security;
struct inode_security_struct *isec;
- isec = kmem_cache_alloc(sel_inode_cache, SLAB_KERNEL);
+ isec = kzalloc(sizeof(struct inode_security_struct), GFP_KERNEL);
if (!isec)
return -ENOMEM;
- memset(isec, 0, sizeof(*isec));
init_MUTEX(&isec->sem);
INIT_LIST_HEAD(&isec->list);
isec->inode = inode;
spin_unlock(&sbsec->isec_lock);
inode->i_security = NULL;
- kmem_cache_free(sel_inode_cache, isec);
+ kfree(isec);
}
static int file_alloc_security(struct file *file)
struct task_security_struct *tsec;
struct inode_security_struct *dsec;
struct superblock_security_struct *sbsec;
+ struct inode_security_struct *isec;
u32 newsid, clen;
int rc;
char *namep = NULL, *context;
tsec = current->security;
dsec = dir->i_security;
sbsec = dir->i_sb->s_security;
+ isec = inode->i_security;
if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
newsid = tsec->create_sid;
inode_security_set_sid(inode, newsid);
- if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
+ if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
return -EOPNOTSUPP;
if (name) {
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(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static int selinux_inode_getsecurity(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))
- return -EOPNOTSUPP;
+ if (strcmp(name, XATTR_SELINUX_SUFFIX)) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
- return selinux_getsecurity(isec->sid, buffer, size);
+ 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 (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;
}
static int selinux_inode_setsecurity(struct inode *inode, const char *name,
static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
{
+#ifndef CONFIG_PPC32
if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
/*
* We are making executable an anonymous mapping or a
if (rc)
return rc;
}
+#endif
if (file) {
/* read access is always possible with a mapping */
if (selinux_checkreqprot)
prot = reqprot;
+#ifndef CONFIG_PPC32
if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
rc = 0;
if (vma->vm_start >= vma->vm_mm->start_brk &&
if (rc)
return rc;
}
+#endif
return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
}
goto out;
/* Handle mapped IPv4 packets arriving via IPv6 sockets */
- if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
+ if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
family = PF_INET;
read_lock_bh(&sk->sk_callback_lock);
return err;
}
-static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
- int __user *optlen, unsigned len)
+static int selinux_socket_getpeersec(struct socket *sock, char __user *optval,
+ int __user *optlen, unsigned len)
{
int err = 0;
char *scontext;
u32 scontext_len;
struct sk_security_struct *ssec;
struct inode_security_struct *isec;
- u32 peer_sid = 0;
isec = SOCK_INODE(sock)->i_security;
-
- /* if UNIX_STREAM check peer_sid, if TCP check dst for labelled sa */
- if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET) {
- ssec = sock->sk->sk_security;
- peer_sid = ssec->peer_sid;
- }
- else if (isec->sclass == SECCLASS_TCP_SOCKET) {
- peer_sid = selinux_socket_getpeer_stream(sock->sk);
-
- if (peer_sid == SECSID_NULL) {
- err = -ENOPROTOOPT;
- goto out;
- }
- }
- else {
+ if (isec->sclass != SECCLASS_UNIX_STREAM_SOCKET) {
err = -ENOPROTOOPT;
goto out;
}
- err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
-
+ ssec = sock->sk->sk_security;
+
+ err = security_sid_to_context(ssec->peer_sid, &scontext, &scontext_len);
if (err)
goto out;
return err;
}
-static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen)
-{
- int err = 0;
- u32 peer_sid = selinux_socket_getpeer_dgram(skb);
-
- if (peer_sid == SECSID_NULL)
- return -EINVAL;
-
- err = security_sid_to_context(peer_sid, secdata, seclen);
- if (err)
- return err;
-
- return 0;
-}
-
-
-
static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
{
return sk_alloc_security(sk, family, priority);
char *name, void *value, size_t size)
{
struct task_security_struct *tsec;
- u32 sid;
+ u32 sid, len;
+ char *context;
int error;
if (current != p) {
return error;
}
+ if (!size)
+ return -ERANGE;
+
tsec = p->security;
if (!strcmp(name, "current"))
if (!sid)
return 0;
- return selinux_getsecurity(sid, value, size);
+ 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;
}
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,
.socket_setsockopt = selinux_socket_setsockopt,
.socket_shutdown = selinux_socket_shutdown,
.socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
- .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
- .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
+ .socket_getpeersec = selinux_socket_getpeersec,
.sk_alloc_security = selinux_sk_alloc_security,
.sk_free_security = selinux_sk_free_security,
.sk_getsid = selinux_sk_getsid_security,
tsec = current->security;
tsec->osid = tsec->sid = SECINITSID_KERNEL;
- sel_inode_cache = kmem_cache_create("selinux_inode_security",
- sizeof(struct inode_security_struct),
- 0, SLAB_PANIC, NULL, NULL);
avc_init();
original_ops = secondary_ops = security_ops;
/* Set up any superblocks initialized prior to the policy load. */
printk(KERN_INFO "SELinux: Setting up existing superblocks.\n");
- spin_lock(&sb_lock);
spin_lock(&sb_security_lock);
next_sb:
if (!list_empty(&superblock_security_head)) {
struct superblock_security_struct,
list);
struct super_block *sb = sbsec->sb;
+ spin_lock(&sb_lock);
sb->s_count++;
- spin_unlock(&sb_security_lock);
spin_unlock(&sb_lock);
+ spin_unlock(&sb_security_lock);
down_read(&sb->s_umount);
if (sb->s_root)
superblock_doinit(sb, NULL);
drop_super(sb);
- spin_lock(&sb_lock);
spin_lock(&sb_security_lock);
list_del_init(&sbsec->list);
goto next_sb;
}
spin_unlock(&sb_security_lock);
- spin_unlock(&sb_lock);
}
/* SELinux requires early initialization in order to label
printk(KERN_INFO "SELinux: Disabled at runtime.\n");
selinux_disabled = 1;
- selinux_enabled = 0;
/* Reset security_ops to the secondary module, dummy or capability. */
security_ops = secondary_ops;