#include <linux/msg.h>
#include <linux/shm.h>
+// [ SEC_SELINUX_PORTING COMMON
+#include <linux/delay.h>
+// ] SEC_SELINUX_PORTING COMMON
+
#include "avc.h"
#include "objsec.h"
#include "netif.h"
unsigned long enforcing;
if (!strict_strtoul(str, 0, &enforcing))
selinux_enforcing = enforcing ? 1 : 0;
+
return 1;
}
__setup("enforcing=", enforcing_setup);
unsigned long enabled;
if (!strict_strtoul(str, 0, &enabled))
selinux_enabled = enabled ? 1 : 0;
+
return 1;
}
__setup("selinux=", selinux_enabled_setup);
sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
sbsec->flags &= ~SE_SBLABELSUPP;
- /* Special handling for sysfs. Is genfs but also has setxattr handler*/
- if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
- sbsec->flags |= SE_SBLABELSUPP;
-
- /*
- * Special handling for rootfs. Is genfs but supports
- * setting SELinux context on in-core inodes.
- */
- if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
+ /* Special handling. Is genfs but also has in-core setxattr handler*/
+ if (!strcmp(sb->s_type->name, "sysfs") ||
+ !strcmp(sb->s_type->name, "pstore") ||
+ !strcmp(sb->s_type->name, "debugfs") ||
+ !strcmp(sb->s_type->name, "tmpfs") ||
+ !strcmp(sb->s_type->name, "rootfs"))
sbsec->flags |= SE_SBLABELSUPP;
/* Initialize the root inode. */
char *context = NULL, *defcontext = NULL;
char *fscontext = NULL, *rootcontext = NULL;
int rc, num_mnt_opts = 0;
-
opts->num_mnt_opts = 0;
/* Standard string-based options. */
goto out_unlock;
sbsec = inode->i_sb->s_security;
+ /* To prevent Null pointer exception */
+ if (!sbsec) {
+ printk(KERN_ERR "[SELinux] sbsec is NULL, inode->i_sb->s_security is already freed. \n");
+ rc = -EINVAL;
+ goto out_unlock;
+ }
+
if (!(sbsec->flags & SE_SBINITIALIZED)) {
/* Defer initialization until selinux_complete_init,
after the initial policy is loaded and the security
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);
}
sid = cred_sid(cred);
isec = inode->i_security;
+ if (unlikely(!isec)){
+ printk(KERN_CRIT "[SELinux] isec is NULL, inode->i_security is already freed. \n");
+ return -EINVAL;
+ }
+
return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
}
{
u32 fromsid = task_sid(from);
u32 tosid = task_sid(to);
+
return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER, NULL);
}
void *data)
{
const struct cred *cred = current_cred();
-
if (flags & MS_REMOUNT)
return superblock_has_perm(cred, path->dentry->d_sb,
FILESYSTEM__REMOUNT, NULL);
sid = cred_sid(cred);
isec = inode->i_security;
+// [ SEC_SELINUX_PORTING COMMON
+ /* skip sid == 1(kernel), it means first boot time */
+ if(isec->initialized != 1 && sid != 1) {
+ int count = 5;
+
+ while(count-- > 0) {
+ printk(KERN_ERR "SELinux : inode->i_security is not initialized. waiting...(%d/5)\n", 5-count);
+ udelay(500);
+ if(isec->initialized == 1) {
+ printk(KERN_ERR "SELinux : inode->i_security is INITIALIZED.\n");
+ break;
+ }
+ }
+ if(isec->initialized != 1) {
+ printk(KERN_ERR "SELinux : inode->i_security is not initialized. not fixed.\n");
+ }
+ }
+// ] SEC_SELINUX_PORTING COMMON
+
rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
audited = avc_audit_required(perms, &avd, rc,
from_access ? FILE__AUDIT_ACCESS : 0,
ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
return dentry_has_perm(cred, dentry, FILE__SETATTR);
- if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
+ if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE)
+ && !(ia_valid & ATTR_FILE))
av |= FILE__OPEN;
return dentry_has_perm(cred, dentry, av);
static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
{
const int len = sizeof(XATTR_NAME_SELINUX);
+
if (buffer && len <= buffer_size)
memcpy(buffer, XATTR_NAME_SELINUX, len);
return len;
file_free_security(file);
}
+/*
+ * Check whether a task has the ioctl permission and cmd
+ * operation to an inode.
+ */
+int ioctl_has_perm(const struct cred *cred, struct file *file,
+ u32 requested, u16 cmd)
+{
+ struct common_audit_data ad;
+ struct file_security_struct *fsec = file->f_security;
+ struct inode *inode = file_inode(file);
+ struct inode_security_struct *isec = inode->i_security;
+ struct lsm_ioctlop_audit ioctl;
+ u32 ssid = cred_sid(cred);
+ int rc;
+ u8 driver = cmd >> 8;
+ u8 xperm = cmd & 0xff;
+
+ ad.type = LSM_AUDIT_DATA_IOCTL_OP;
+ ad.u.op = &ioctl;
+ ad.u.op->cmd = cmd;
+ ad.u.op->path = file->f_path;
+
+ if (ssid != fsec->sid) {
+ rc = avc_has_perm(ssid, fsec->sid,
+ SECCLASS_FD,
+ FD__USE,
+ &ad);
+ if (rc)
+ goto out;
+ }
+
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
+ rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
+ requested, driver, xperm, &ad);
+out:
+ return rc;
+}
+
static int selinux_file_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
* to the file's ioctl() function.
*/
default:
- error = file_has_perm(cred, file, FILE__IOCTL);
+ error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
}
return error;
}
static int selinux_task_setioprio(struct task_struct *p, int ioprio)
{
int rc;
-
rc = cap_task_setioprio(p, ioprio);
if (rc)
return rc;
struct lsm_network_audit net = {0,};
u32 tsid = task_sid(task);
+ if (unlikely(!sksec)){
+ printk(KERN_CRIT "[SELinux] sksec is NULL, socket is already freed. \n");
+ return -EINVAL;
+ }
+
if (sksec->sid == SECINITSID_KERNEL)
return 0;
static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
{
int len = 0;
+
len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
ctx, true);
if (len < 0)
static int __init selinux_nf_ip_init(void)
{
int err = 0;
-
if (!selinux_enabled)
goto out;