2013年9月19日 星期四

Selinux from user-space to kernel

//build in debug mode
modify $home/myandroid/system/core/init/property_service.h
int property_get(const char *name, char *value)
{
    /*size_t value_len = __builtin_object_size(value, 0);
    if (value_len != PROP_VALUE_MAX)
        __property_get_size_error();*/

    return __property_get(name, value);
}

$home/myandroid/external/libselinux/src/avc.c
int avc_has_perm_noaudit(...)
{
...
...
      if (!ae)
     {
        avc_cache_stats_incr(entry_misses);
        rc = avc_lookup(ssid, tsid, tclass, requested, aeref);
        if (rc)
        {
            //trace into this function
            rc = security_compute_av(ssid->ctx, tsid->ctx, tclass, requested, &entry.avd);
            if (rc && errno == EINVAL && !avc_enforcing)
            {
                rc = errno = 0;
                goto out;
            }
            if (rc)
                goto out;
            rc = avc_insert(ssid, tsid, tclass, &entry, aeref);
            if (rc)
                goto out;
        }
        ae = aeref->ae;
    }
...
...
}

//then goto

$home/myandroid/external/libselinux/src/compute_av.c
int security_compute_av(const char * scon,
            const char * tcon,
            security_class_t tclass,
            access_vector_t requested,
            struct av_decision *avd)
{
    char path[PATH_MAX];
    char *buf;
    size_t len;
    int fd, ret;

    if (!selinux_mnt) {
        errno = ENOENT;
        return -1;
    }

    //path = /sys/fs/selinux/access
    snprintf(path, sizeof path, "%s/access", selinux_mnt);
    fd = open(path, O_RDWR);
    if (fd < 0)
        return -1;

    len = selinux_page_size;
    buf = malloc(len);
    if (!buf) {
        ret = -1;
        goto out;
    }

    snprintf(buf, len, "%s %s %hu %x", scon, tcon, unmap_class(tclass), unmap_perm(tclass, requested));

    ret = write(fd, buf, strlen(buf));  //goto kernel sel_write_access
    if (ret < 0)
        goto out2;

    memset(buf, 0, len);
    ret = read(fd, buf, len - 1);  //read selinuxfs.c buf data
    if (ret < 0)
        goto out2;

    ret = sscanf(buf, "%x %x %x %x %u %x",
             &avd->allowed, &avd->decided,
             &avd->auditallow, &avd->auditdeny,
             &avd->seqno, &avd->flags);
    if (ret < 5) {
        ret = -1;
        goto out2;
    } else if (ret < 6)
        avd->flags = 0;

    map_decision(tclass, avd);

    ret = 0;
      out2:
    free(buf);
      out:
    close(fd);
    return ret;
}


//then goto

$home/myandroid/kernel_imx/security/selinux/selinuxfs.c
static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
{
    char *scon = NULL, *tcon = NULL;
    u32 ssid, tsid;
    u16 tclass;
    struct av_decision avd;
    ssize_t length;

    length = task_has_security(current, SECURITY__COMPUTE_AV);
    if (length)
        goto out;

    length = -ENOMEM;
    scon = kzalloc(size + 1, GFP_KERNEL);
    if (!scon)
        goto out;

    length = -ENOMEM;
    tcon = kzalloc(size + 1, GFP_KERNEL);
    if (!tcon)
        goto out;

    length = -EINVAL;
    if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
        goto out;

    length = security_context_to_sid(scon, strlen(scon) + 1, &ssid,
                     GFP_KERNEL);
    if (length)
        goto out;

    length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid,
                     GFP_KERNEL);
    if (length)
        goto out;

    //compare policy database and get avd data
    security_compute_av_user(ssid, tsid, tclass, &avd);

    length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
              "%x %x %x %x %u %x",
              avd.allowed, 0xffffffff,
              avd.auditallow, avd.auditdeny,
              avd.seqno, avd.flags);
out:
    kfree(tcon);
    kfree(scon);
    return length;
}

trace step:
http://www.mediafire.com/file/c2bbm3o23uj5big/selinux.tar.gz

沒有留言:

張貼留言