为什么在AOSP 7.1.2上出现getpidcon()错误?

时间:2018-08-16 01:03:06

标签: android selinux seandroid

我正在根据AOSP Nougat最新消息制作定制的bsp。

Android服务流程要求服务管理员查找或添加服务。 服务管理器会尝试通过调用svc_can_register()或svc_can_find()来调用mac_perms()来检查mac权限。

让我们看看svc_can_find()

static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
{
    const char *perm = "find";
    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
}

check_mac_perms_from_lookup()就像这样:

static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name)
{
    bool allowed;
    char *tctx = NULL;

    if (selinux_enabled <= 0) {
        return true;
    }

    if (!sehandle) {
        ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");
        abort();
    }

    if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {
        ALOGE("SELinux: No match for %s in service_contexts.\n", name);
        return false;
    }

    allowed = check_mac_perms(spid, uid, tctx, perm, name);
    freecon(tctx);
    return allowed;
}

它调用check_mac_perms()。像这样的check_mac_perms():

static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
{
    char *sctx = NULL;
    const char *class = "service_manager";
    bool allowed;
    struct audit_data ad;
    if (getpidcon(spid, &sctx) < 0) {
        ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
        return false;
    }
    ad.pid = spid;
    ad.uid = uid;
    ad.name = name;
    int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad);
    allowed = (result == 0);
    freecon(sctx);
    return allowed;
}

它调用getpidcon()。 getpidcon()在 外部/selinux/libselinux/src/procattr.c

getpidcon()的定义如下:

#define getpidattr_def(fn, attr) \
    int get##fn(pid_t pid, char **c)    \
    { \
        if (pid <= 0) { \
            errno = EINVAL; \
            return -1; \
        } else { \
            return getprocattrcon(c, pid, #attr); \
        } \
    }

...
...
    getpidattr_def(pidcon, current)

“ getpidattr_def(pidcon,current)”扩展为getpidcon()函数 定义并调用getprocatrcon()

getprocattrcon()就像这样:

static int getprocattrcon(char ** context,
              pid_t pid, const char *attr)
{
    char *buf;
    size_t size;
    int fd;
    ssize_t ret;
    int errno_hold;

    fd = openattr(pid, attr, O_RDONLY);
    if (fd < 0)
        return -1;

    size = selinux_page_size;
    buf = malloc(size);
    if (!buf) {
        ret = -1;
        goto out;
    }
    memset(buf, 0, size);

    do {
        ret = read(fd, buf, size - 1);
    } while (ret < 0 && errno == EINTR);
    if (ret < 0)
        goto out2;

    if (ret == 0) {
        *context = NULL;
        goto out2;
    }

    *context = strdup(buf);
    if (!(*context)) {
        ret = -1;
        goto out2;
    }

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

很简单吧?只是打开一些文件并阅读内容 并通过函数参数返回它。

在openattr()失败。我已经通过在其中插入一些日志功能来确认这一点 openattr()。 openattr()也是简单的函数。

static int openattr(pid_t pid, const char *attr, int flags)
{
    int fd, rc;
    char *path;
    pid_t tid;

    if (pid > 0) {
        rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr);
    } else if (pid == 0) {
        rc = asprintf(&path, "/proc/thread-self/attr/%s", attr);
        if (rc < 0)
            return -1;
        fd = open(path, flags | O_CLOEXEC);
        if (fd >= 0 || errno != ENOENT)
            goto out;
        free(path);
        tid = gettid();
        rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr);
    } else {
        errno = EINVAL;
        return -1;
    }
    if (rc < 0)
        return -1;

    fd = open(path, flags | O_CLOEXEC);
out:
    free(path);
    return fd;
}

失败点是“ fd = open(路径,标志| O_CLOEXEC);”

即使文件存在,几乎总是无法打开。我不明白,想知道是什么原因引起的。我已确认失败 通过插入一些日志打印代码,检查android log(adb logcat)并从android shell(adb shell)中读取文件,例如'cat / proc / 412 / attr / current'。成功读取“ cat ...”,但日志显示打开 文件失败。奇怪的是,如果'pid'为0,则表示成功。

如果打开失败,则无法启动服务,因此系统不会 正常启动。如果我忽略失败并从getpidcon()返回成功 系统可以正常启动,但这显然不是正确的事情。

我正在将bsp测试为selinux许可模式。

谁能像我一样经历?如果有人,请分享 经验和解决问题的方法。

谢谢。 李三gy。

0 个答案:

没有答案