#include <linux/personality.h>
#include <linux/sysctl.h>
#include <linux/audit.h>
+#include <linux/string.h>
#include "avc.h"
#include "objsec.h"
return SECCLASS_NETLINK_ROUTE_SOCKET;
case NETLINK_FIREWALL:
return SECCLASS_NETLINK_FIREWALL_SOCKET;
- case NETLINK_TCPDIAG:
+ case NETLINK_INET_DIAG:
return SECCLASS_NETLINK_TCPDIAG_SOCKET;
case NETLINK_NFLOG:
return SECCLASS_NETLINK_NFLOG_SOCKET;
sid = sbsec->def_sid;
rc = 0;
} else {
- rc = security_context_to_sid(context, rc, &sid);
+ rc = security_context_to_sid_default(context, rc, &sid,
+ sbsec->def_sid);
if (rc) {
printk(KERN_WARNING "%s: context_to_sid(%s) "
"returned %d for dev=%s ino=%ld\n",
struct inode *inode;
struct inode_security_struct *dsec;
struct superblock_security_struct *sbsec;
+ struct inode_security_struct *isec;
u32 newsid;
char *context;
unsigned int len;
return 0;
}
+ isec = inode->i_security;
+
+ if (isec->security_attr_init)
+ return 0;
+
if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
newsid = tsec->create_sid;
} else {
static void selinux_bprm_free_security(struct linux_binprm *bprm)
{
- struct bprm_security_struct *bsec = bprm->security;
+ kfree(bprm->security);
bprm->security = NULL;
- kfree(bsec);
}
extern struct vfsmount *selinuxfs_mount;
}
} while (*in_end++);
- copy_page(in_save, nosec_save);
+ strcpy(in_save, nosec_save);
+ free_page((unsigned long)nosec_save);
out:
return rc;
}
inode_free_security(inode);
}
+static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
+ char **name, void **value,
+ size_t *len)
+{
+ 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;
+ } else {
+ rc = security_transition_sid(tsec->sid, dsec->sid,
+ inode_mode_to_security_class(inode->i_mode),
+ &newsid);
+ if (rc) {
+ printk(KERN_WARNING "%s: "
+ "security_transition_sid failed, rc=%d (dev=%s "
+ "ino=%ld)\n",
+ __FUNCTION__,
+ -rc, inode->i_sb->s_id, inode->i_ino);
+ return rc;
+ }
+ }
+
+ inode_security_set_sid(inode, newsid);
+
+ if (name) {
+ namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL);
+ if (!namep)
+ return -ENOMEM;
+ *name = namep;
+ }
+
+ if (value && len) {
+ rc = security_sid_to_context(newsid, &context, &clen);
+ if (rc) {
+ kfree(namep);
+ return rc;
+ }
+ *value = context;
+ *len = clen;
+ }
+
+ isec->security_attr_init = 1;
+
+ return 0;
+}
+
static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
{
return may_create(dir, dentry, SECCLASS_FILE);
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
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 (rc)
+ return rc;
+ }
#endif
return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
nexthdr = ip6->nexthdr;
offset += sizeof(_ipv6h);
- offset = ipv6_skip_exthdr(skb, offset, &nexthdr,
- skb->tail - skb->head - offset);
+ offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
if (offset < 0)
goto out;
if (sk->sk_family == PF_INET) {
addr4 = (struct sockaddr_in *)address;
- if (addrlen != sizeof(struct sockaddr_in))
+ if (addrlen < sizeof(struct sockaddr_in))
return -EINVAL;
snum = ntohs(addr4->sin_port);
} else {
addr6 = (struct sockaddr_in6 *)address;
- if (addrlen != sizeof(struct sockaddr_in6))
+ if (addrlen < SIN6_LEN_RFC2133)
return -EINVAL;
snum = ntohs(addr6->sin6_port);
}
err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
if (err) {
if (err == -EINVAL) {
- audit_log(current->audit_context,
+ audit_log(current->audit_context, AUDIT_SELINUX_ERR,
"SELinux: unrecognized netlink message"
" type=%hu for sclass=%hu\n",
nlh->nlmsg_type, isec->sclass);
}
static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
- u16 sclass, u32 perms)
+ u32 perms)
{
struct task_security_struct *tsec;
struct ipc_security_struct *isec;
AVC_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = ipc_perms->key;
- return avc_has_perm(tsec->sid, isec->sid, sclass, perms, &ad);
+ return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
}
static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
return 0;
}
- err = ipc_has_perm(&msq->q_perm, SECCLASS_MSGQ, perms);
+ err = ipc_has_perm(&msq->q_perm, perms);
return err;
}
return 0;
}
- err = ipc_has_perm(&shp->shm_perm, SECCLASS_SHM, perms);
+ err = ipc_has_perm(&shp->shm_perm, perms);
return err;
}
else
perms = SHM__READ | SHM__WRITE;
- return ipc_has_perm(&shp->shm_perm, SECCLASS_SHM, perms);
+ return ipc_has_perm(&shp->shm_perm, perms);
}
/* Semaphore security operations */
return 0;
}
- err = ipc_has_perm(&sma->sem_perm, SECCLASS_SEM, perms);
+ err = ipc_has_perm(&sma->sem_perm, perms);
return err;
}
else
perms = SEM__READ;
- return ipc_has_perm(&sma->sem_perm, SECCLASS_SEM, perms);
+ return ipc_has_perm(&sma->sem_perm, perms);
}
static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
{
- struct ipc_security_struct *isec = ipcp->security;
- u16 sclass = SECCLASS_IPC;
u32 av = 0;
- if (isec && isec->magic == SELINUX_MAGIC)
- sclass = isec->sclass;
-
av = 0;
if (flag & S_IRUGO)
av |= IPC__UNIX_READ;
if (av == 0)
return 0;
- return ipc_has_perm(ipcp, sclass, av);
+ return ipc_has_perm(ipcp, av);
}
/* module stacking operations */
.inode_alloc_security = selinux_inode_alloc_security,
.inode_free_security = selinux_inode_free_security,
+ .inode_init_security = selinux_inode_init_security,
.inode_create = selinux_inode_create,
.inode_post_create = selinux_inode_post_create,
.inode_link = selinux_inode_link,