示例#1
0
文件: nss_mc_common.c 项目: SSSD/sssd
errno_t sss_nss_check_header(struct sss_cli_mc_ctx *ctx)
{
    struct sss_mc_header h;
    bool copy_ok;
    int count;
    int ret;
    struct stat fdstat;

    /* retry barrier protected reading max 5 times then give up */
    for (count = 5; count > 0; count--) {
        MEMCPY_WITH_BARRIERS(copy_ok, &h,
                             (struct sss_mc_header *)ctx->mmap_base,
                             sizeof(struct sss_mc_header));
        if (copy_ok) {
            /* record is consistent so we can proceed */
            break;
        }
    }
    if (count == 0) {
        /* couldn't successfully read header we have to give up */
        return EIO;
    }

    if (h.major_vno != SSS_MC_MAJOR_VNO ||
        h.minor_vno != SSS_MC_MINOR_VNO ||
        h.status == SSS_MC_HEADER_RECYCLED) {
        return EINVAL;
    }

    /* first time we check the header, let's fill our own struct */
    if (ctx->data_table == NULL) {
        ctx->seed = h.seed;
        ctx->data_table = MC_PTR_ADD(ctx->mmap_base, h.data_table);
        ctx->hash_table = MC_PTR_ADD(ctx->mmap_base, h.hash_table);
        ctx->dt_size = h.dt_size;
        ctx->ht_size = h.ht_size;
    } else {
        if (ctx->seed != h.seed ||
            ctx->data_table != MC_PTR_ADD(ctx->mmap_base, h.data_table) ||
            ctx->hash_table != MC_PTR_ADD(ctx->mmap_base, h.hash_table) ||
            ctx->dt_size != h.dt_size ||
            ctx->ht_size != h.ht_size) {
            return EINVAL;
        }
    }

    ret = fstat(ctx->fd, &fdstat);
    if (ret == -1) {
        return EIO;
    }

    if (fdstat.st_nlink == 0) {
        /* memory cache was removed; we need to reinitialize it. */
        return EINVAL;
    }

    return 0;
}
示例#2
0
errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name,
                            enum sss_mc_type type, size_t n_elem,
                            time_t timeout, struct sss_mc_ctx **mcc)
{
    struct sss_mc_ctx *mc_ctx = NULL;
    unsigned int rseed;
    int payload;
    int ret;

    switch (type) {
    case SSS_MC_PASSWD:
        payload = SSS_AVG_PASSWD_PAYLOAD;
        break;
    case SSS_MC_GROUP:
        payload = SSS_AVG_GROUP_PAYLOAD;
        break;
    default:
        return EINVAL;
    }

    mc_ctx = talloc_zero(mem_ctx, struct sss_mc_ctx);
    if (!mc_ctx) {
        return ENOMEM;
    }
    mc_ctx->fd = -1;

    mc_ctx->name = talloc_strdup(mem_ctx, name);
    if (!mc_ctx->name) {
        ret = ENOMEM;
        goto done;
    }

    mc_ctx->type = type;

    mc_ctx->valid_time_slot = timeout;

    mc_ctx->file = talloc_asprintf(mc_ctx, "%s/%s",
                                   SSS_NSS_MCACHE_DIR, name);
    if (!mc_ctx->file) {
        ret = ENOMEM;
        goto done;
    }

    /* elements must always be multiple of 8 to make things easier to handle,
     * so we increase by the necessary amount if they are not a multiple */
    /* We can use MC_ALIGN64 for this */
    n_elem = MC_ALIGN64(n_elem);

    /* hash table is double the size because it will store both forward and
     * reverse keys (name/uid, name/gid, ..) */
    mc_ctx->ht_size = MC_HT_SIZE(n_elem * 2);
    mc_ctx->dt_size = MC_DT_SIZE(n_elem, payload);
    mc_ctx->ft_size = MC_FT_SIZE(n_elem);
    mc_ctx->mmap_size = MC_HEADER_SIZE +
                        MC_ALIGN64(mc_ctx->dt_size) +
                        MC_ALIGN64(mc_ctx->ft_size) +
                        MC_ALIGN64(mc_ctx->ht_size);


    /* for now ALWAYS create a new file on restart */

    ret = sss_mc_create_file(mc_ctx);
    if (ret) {
        goto done;
    }

    ret = ftruncate(mc_ctx->fd, mc_ctx->mmap_size);
    if (ret == -1) {
        ret = errno;
        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to resize file %s: %d(%s)\n",
                                    mc_ctx->file, ret, strerror(ret)));
        goto done;
    }

    mc_ctx->mmap_base = mmap(NULL, mc_ctx->mmap_size,
                             PROT_READ | PROT_WRITE,
                             MAP_SHARED, mc_ctx->fd, 0);
    if (mc_ctx->mmap_base == MAP_FAILED) {
        ret = errno;
        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to mmap file %s(%ld): %d(%s)\n",
                                    mc_ctx->file, mc_ctx->mmap_size,
                                    ret, strerror(ret)));
        goto done;
    }

    mc_ctx->data_table = MC_PTR_ADD(mc_ctx->mmap_base, MC_HEADER_SIZE);
    mc_ctx->free_table = MC_PTR_ADD(mc_ctx->data_table,
                                    MC_ALIGN64(mc_ctx->dt_size));
    mc_ctx->hash_table = MC_PTR_ADD(mc_ctx->free_table,
                                    MC_ALIGN64(mc_ctx->ft_size));

    memset(mc_ctx->data_table, 0x00, mc_ctx->dt_size);
    memset(mc_ctx->free_table, 0x00, mc_ctx->ft_size);
    memset(mc_ctx->hash_table, 0xff, mc_ctx->ht_size);

    /* generate a pseudo-random seed.
     * Needed to fend off dictionary based collision attacks */
    rseed = time(NULL) * getpid();
    mc_ctx->seed = rand_r(&rseed);

    sss_mc_header_update(mc_ctx, SSS_MC_HEADER_ALIVE);

    ret = EOK;

done:
    if (ret) {
        if (mc_ctx && mc_ctx->mmap_base) {
            munmap(mc_ctx->mmap_base, mc_ctx->mmap_size);
        }
        if (mc_ctx && mc_ctx->fd != -1) {
            close(mc_ctx->fd);
            ret = unlink(mc_ctx->file);
            if (ret == -1) {
                DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to rm mmap file %s: %d(%s)\n",
                                            mc_ctx->file, ret, strerror(ret)));
            }
        }

        talloc_free(mc_ctx);
    } else {
        *mcc = mc_ctx;
    }
    return ret;
}