X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=security%2Fselinux%2Fhooks.c;h=b65c201e9ff50386ea6cb43ed2c0c91f63a4cfe7;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=9fcb30dab94f3fb13b490db2c0822aef22b5321f;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9fcb30dab..b65c201e9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -101,8 +101,6 @@ static int __init selinux_enabled_setup(char *str) return 1; } __setup("selinux=", selinux_enabled_setup); -#else -int selinux_enabled = 1; #endif /* Original (dummy) security module. */ @@ -119,34 +117,6 @@ static struct security_operations *secondary_ops = NULL; 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) @@ -176,11 +146,10 @@ static int inode_alloc_security(struct inode *inode) 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; @@ -203,7 +172,7 @@ static void inode_free_security(struct 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) @@ -1960,6 +1929,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, 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; @@ -1967,6 +1937,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, 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; @@ -1986,7 +1957,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, 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) { @@ -2238,11 +2209,6 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *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 @@ -2250,14 +2216,47 @@ static const char *selinux_inode_xattr_getsuffix(void) * * 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, @@ -2366,6 +2365,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, 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 @@ -2376,6 +2376,7 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared if (rc) return rc; } +#endif if (file) { /* read access is always possible with a mapping */ @@ -2422,6 +2423,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, 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 && @@ -2446,6 +2448,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, if (rc) return rc; } +#endif return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); } @@ -3227,7 +3230,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 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); @@ -3315,38 +3318,24 @@ out: 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; @@ -3367,23 +3356,6 @@ 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); @@ -4091,7 +4063,8 @@ static int selinux_getprocattr(struct task_struct *p, char *name, void *value, size_t size) { struct task_security_struct *tsec; - u32 sid; + u32 sid, len; + char *context; int error; if (current != p) { @@ -4100,6 +4073,9 @@ static int selinux_getprocattr(struct task_struct *p, return error; } + if (!size) + return -ERANGE; + tsec = p->security; if (!strcmp(name, "current")) @@ -4116,7 +4092,16 @@ static int selinux_getprocattr(struct task_struct *p, 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, @@ -4274,7 +4259,6 @@ static struct security_operations selinux_ops = { .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, @@ -4360,8 +4344,7 @@ static struct security_operations selinux_ops = { .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, @@ -4393,9 +4376,6 @@ static __init int selinux_init(void) 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; @@ -4418,7 +4398,6 @@ void selinux_complete_init(void) /* 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)) { @@ -4427,20 +4406,19 @@ next_sb: 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 @@ -4535,7 +4513,6 @@ int selinux_disable(void) 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;