Ejemplo n.º 1
0
static bool sss_mc_is_valid_rec(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec)
{
    struct sss_mc_rec *self;
    uint32_t slot;

    if (((uint8_t *)rec < mcc->data_table) ||
        ((uint8_t *)rec > (mcc->data_table + mcc->dt_size - MC_SLOT_SIZE))) {
        return false;
    }

    if ((rec->b1 == MC_INVALID_VAL) ||
        (rec->b1 != rec->b2)) {
        return false;
    }

    if (!MC_CHECK_RECORD_LENGTH(mcc, rec)) {
        return false;
    }

    if (rec->expire == MC_INVALID_VAL64) {
        return false;
    }

    /* rec->next can be invalid if there are no next records */

    if (rec->hash1 == MC_INVALID_VAL32) {
        return false;
    } else {
        self = NULL;
        slot = mcc->hash_table[rec->hash1];
        while (slot != MC_INVALID_VAL32 && self != rec) {
            self = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
            slot = self->next;
        }
        if (self != rec) {
            return false;
        }
    }
    if (rec->hash2 != MC_INVALID_VAL32) {
        self = NULL;
        slot = mcc->hash_table[rec->hash2];
        while (slot != MC_INVALID_VAL32 && self != rec) {
            self = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
            slot = self->next;
        }
        if (self != rec) {
            return false;
        }
    }
Ejemplo n.º 2
0
errno_t sss_nss_mc_get_record(struct sss_cli_mc_ctx *ctx,
                              uint32_t slot, struct sss_mc_rec **_rec)
{
    struct sss_mc_rec *rec;
    struct sss_mc_rec *copy_rec = NULL;
    size_t buf_size = 0;
    size_t rec_len;
    uint32_t b1;
    uint32_t b2;
    bool copy_ok;
    int count;
    int ret;

    /* try max 5 times */
    for (count = 5; count > 0; count--) {
        rec = MC_SLOT_TO_PTR(ctx->data_table, slot, struct sss_mc_rec);

        /* fetch record length */
        b1 = rec->b1;
        __sync_synchronize();
        rec_len = rec->len;
        __sync_synchronize();
        b2 = rec->b2;
        if (!MC_VALID_BARRIER(b1) || b1 != b2) {
            /* record is inconsistent, retry */
            continue;
        }

        if (!MC_CHECK_RECORD_LENGTH(ctx, rec)) {
            /* record has invalid length */
            free(copy_rec);
            return EINVAL;
        }

        if (rec_len > buf_size) {
            free(copy_rec);
            copy_rec = malloc(rec_len);
            if (!copy_rec) {
                ret = ENOMEM;
                goto done;
            }
            buf_size = rec_len;
        }
        /* we cannot access data directly, we must copy data and then
         * access the copy */
        MEMCPY_WITH_BARRIERS(copy_ok, copy_rec, rec, rec_len);

        /* we must check data is consistent again after the copy */
        if (copy_ok && b1 == copy_rec->b2) {
            /* record is consistent, use it */
            break;
        }
    }
    if (count == 0) {
        /* couldn't successfully read header we have to give up */
        ret = EIO;
        goto done;
    }

    *_rec = copy_rec;
    ret = 0;

done:
    if (ret) {
        free(copy_rec);
        *_rec = NULL;
    }
    return ret;
}