eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce/*
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce SSSD
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce NSS Responder - Mmap Cache
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce Copyright (C) Simo Sorce <ssorce@redhat.com> 2011
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce This program is free software; you can redistribute it and/or modify
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce it under the terms of the GNU General Public License as published by
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce the Free Software Foundation; either version 3 of the License, or
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce (at your option) any later version.
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce This program is distributed in the hope that it will be useful,
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce but WITHOUT ANY WARRANTY; without even the implied warranty of
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce GNU General Public License for more details.
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce You should have received a copy of the GNU General Public License
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce along with this program. If not, see <http://www.gnu.org/licenses/>.
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce*/
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce#include "util/util.h"
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce#include "confdb/confdb.h"
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce#include <sys/mman.h>
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce#include <fcntl.h>
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce#include "util/mmap_cache.h"
4049b63f8c67ada17b453463b0451ca6be3d5de4Pavel Březina#include "responder/nss/nss_private.h"
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce#include "responder/nss/nsssrv_mmap_cache.h"
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce/* arbitrary (avg of my /etc/passwd) */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce#define SSS_AVG_PASSWD_PAYLOAD (MC_SLOT_SIZE * 4)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce/* short group name and no gids (private user group */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce#define SSS_AVG_GROUP_PAYLOAD (MC_SLOT_SIZE * 3)
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik/* average place for 40 supplementary groups + 2 names */
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik#define SSS_AVG_INITGROUP_PAYLOAD (MC_SLOT_SIZE * 5)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce#define MC_NEXT_BARRIER(val) ((((val) + 1) & 0x00ffffff) | 0xf0000000)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce#define MC_RAISE_BARRIER(m) do { \
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce m->b2 = MC_NEXT_BARRIER(m->b1); \
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce __sync_synchronize(); \
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce} while (0)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce#define MC_LOWER_BARRIER(m) do { \
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce __sync_synchronize(); \
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce m->b1 = m->b2; \
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce} while (0)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce#define MC_RAISE_INVALID_BARRIER(m) do { \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce m->b2 = MC_INVALID_VAL; \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce __sync_synchronize(); \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce} while (0)
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorcestruct sss_mc_ctx {
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce char *name; /* mmap cache name */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce enum sss_mc_type type; /* mmap cache type */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce char *file; /* mmap cache file name */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce int fd; /* file descriptor */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce uint32_t seed; /* pseudo-random seed to avoid collision attacks */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce time_t valid_time_slot; /* maximum time the entry is valid in seconds */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce void *mmap_base; /* base address of mmap */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce size_t mmap_size; /* total size of mmap */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce uint32_t *hash_table; /* hash table address (in mmap) */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce uint32_t ht_size; /* size of hash table */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce uint8_t *free_table; /* free list bitmaps */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce uint32_t ft_size; /* size of free table */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce uint32_t next_slot; /* the next slot after last allocation */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce uint8_t *data_table; /* data table address (in mmap) */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce uint32_t dt_size; /* size of data table */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce};
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce#define MC_FIND_BIT(base, num) \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t n = (num); \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint8_t *b = (base) + n / 8; \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint8_t c = 0x80 >> (n % 8);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce#define MC_SET_BIT(base, num) do { \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce MC_FIND_BIT(base, num) \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce *b |= c; \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce} while (0)
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce#define MC_CLEAR_BIT(base, num) do { \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce MC_FIND_BIT(base, num) \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce *b &= ~c; \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce} while (0)
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce#define MC_PROBE_BIT(base, num, used) do { \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce MC_FIND_BIT(base, num) \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (*b & c) used = true; \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce else used = false; \
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce} while (0)
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnikstatic inline
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnikuint32_t sss_mc_next_slot_with_hash(struct sss_mc_rec *rec,
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik uint32_t hash)
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik{
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik if (rec->hash1 == hash) {
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik return rec->next1;
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik } else if (rec->hash2 == hash) {
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik return rec->next2;
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik } else {
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik /* it should never happen. */
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik return MC_INVALID_VAL;
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik }
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik}
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnikstatic inline
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnikvoid sss_mc_chain_slot_to_record_with_hash(struct sss_mc_rec *rec,
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik uint32_t hash,
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik uint32_t slot)
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik{
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik /* changing a single uint32_t is atomic, so there is no
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik * need to use barriers in this case */
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik if (rec->hash1 == hash) {
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik rec->next1 = slot;
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik } else if (rec->hash2 == hash) {
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik rec->next2 = slot;
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik }
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik}
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek/* This function will store corrupted memcache to disk for later
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek * analysis. */
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidekstatic void sss_mc_save_corrupted(struct sss_mc_ctx *mc_ctx)
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek{
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek int err;
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek int fd = -1;
1f7fb30cc25765e54841e5d5f4192c12e3b29a16Michal Zidek ssize_t written = -1;
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek char *file = NULL;
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek TALLOC_CTX *tmp_ctx;
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek if (mc_ctx == NULL) {
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek DEBUG(SSSDBG_TRACE_FUNC,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Cannot store uninitialized cache. Nothing to do.\n");
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek return;
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek }
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek tmp_ctx = talloc_new(NULL);
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek if (tmp_ctx == NULL) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory.\n");
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek return;
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek }
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek file = talloc_asprintf(tmp_ctx, "%s_%s",
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek mc_ctx->file, "corrupted");
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek if (file == NULL) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory.\n");
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek goto done;
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek }
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek /* We will always store only the last problematic cache state */
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek fd = creat(file, 0600);
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek if (fd == -1) {
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek err = errno;
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek DEBUG(SSSDBG_CRIT_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Failed to open file '%s' [%d]: %s\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov file, err, strerror(err));
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek goto done;
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek }
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek
1f7fb30cc25765e54841e5d5f4192c12e3b29a16Michal Zidek written = sss_atomic_write_s(fd, mc_ctx->mmap_base, mc_ctx->mmap_size);
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek if (written != mc_ctx->mmap_size) {
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek if (written == -1) {
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek err = errno;
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek DEBUG(SSSDBG_CRIT_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "write() failed [%d]: %s\n", err, strerror(err));
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek } else {
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek DEBUG(SSSDBG_CRIT_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "write() returned %zd (expected (%zd))\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov written, mc_ctx->mmap_size);
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek }
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek goto done;
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek }
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek sss_log(SSS_LOG_NOTICE,
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek "Stored copy of corrupted mmap cache in file '%s\n'", file);
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidekdone:
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek if (fd != -1) {
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek close(fd);
1f7fb30cc25765e54841e5d5f4192c12e3b29a16Michal Zidek if (written == -1) {
1f7fb30cc25765e54841e5d5f4192c12e3b29a16Michal Zidek err = unlink(file);
1f7fb30cc25765e54841e5d5f4192c12e3b29a16Michal Zidek if (err != 0) {
1f7fb30cc25765e54841e5d5f4192c12e3b29a16Michal Zidek err = errno;
1f7fb30cc25765e54841e5d5f4192c12e3b29a16Michal Zidek DEBUG(SSSDBG_CRIT_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Failed to remove file '%s': %s.\n", file,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov strerror(err));
1f7fb30cc25765e54841e5d5f4192c12e3b29a16Michal Zidek }
1f7fb30cc25765e54841e5d5f4192c12e3b29a16Michal Zidek }
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek }
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek talloc_free(tmp_ctx);
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek}
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorcestatic uint32_t sss_mc_hash(struct sss_mc_ctx *mcc,
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce const char *key, size_t len)
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce{
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce return murmurhash3(key, len, mcc->seed) % MC_HT_ELEMS(mcc->ht_size);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce}
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorcestatic void sss_mc_add_rec_to_chain(struct sss_mc_ctx *mcc,
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce struct sss_mc_rec *rec,
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t hash)
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce{
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce struct sss_mc_rec *cur;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t slot;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
b8d0374cd23db90fce203292ff547641f62e338aLukas Slebodnik if (hash > MC_HT_ELEMS(mcc->ht_size)) {
8437e782fdf97945e9e0c2a793ffaf49abc2c0caSimo Sorce /* Invalid hash. This should never happen, but better
8437e782fdf97945e9e0c2a793ffaf49abc2c0caSimo Sorce * return than trying to access out of bounds memory */
8437e782fdf97945e9e0c2a793ffaf49abc2c0caSimo Sorce return;
8437e782fdf97945e9e0c2a793ffaf49abc2c0caSimo Sorce }
8437e782fdf97945e9e0c2a793ffaf49abc2c0caSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce slot = mcc->hash_table[hash];
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (slot == MC_INVALID_VAL) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* no previous record/collision, just add to hash table */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce mcc->hash_table[hash] = MC_PTR_TO_SLOT(mcc->data_table, rec);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce return;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce do {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (cur == rec) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* rec already stored in hash chain */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce return;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik slot = sss_mc_next_slot_with_hash(cur, hash);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce } while (slot != MC_INVALID_VAL);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* end of chain, append our record here */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik slot = MC_PTR_TO_SLOT(mcc->data_table, rec);
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik sss_mc_chain_slot_to_record_with_hash(cur, hash, slot);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce}
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorcestatic void sss_mc_rm_rec_from_chain(struct sss_mc_ctx *mcc,
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce struct sss_mc_rec *rec,
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t hash)
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce{
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce struct sss_mc_rec *prev = NULL;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce struct sss_mc_rec *cur = NULL;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t slot;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
b8d0374cd23db90fce203292ff547641f62e338aLukas Slebodnik if (hash > MC_HT_ELEMS(mcc->ht_size)) {
b8d0374cd23db90fce203292ff547641f62e338aLukas Slebodnik /* It can happen if rec->hash1 and rec->hash2 was the same.
b8d0374cd23db90fce203292ff547641f62e338aLukas Slebodnik * or it is invalid hash. It is better to return
b8d0374cd23db90fce203292ff547641f62e338aLukas Slebodnik * than trying to access out of bounds memory
b8d0374cd23db90fce203292ff547641f62e338aLukas Slebodnik */
8437e782fdf97945e9e0c2a793ffaf49abc2c0caSimo Sorce return;
8437e782fdf97945e9e0c2a793ffaf49abc2c0caSimo Sorce }
8437e782fdf97945e9e0c2a793ffaf49abc2c0caSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce slot = mcc->hash_table[hash];
27ea6c34e9d8a914b0aeebe9ca98eb65dea404d0Lukas Slebodnik if (slot == MC_INVALID_VAL) {
27ea6c34e9d8a914b0aeebe9ca98eb65dea404d0Lukas Slebodnik /* record has already been removed. It may happen if rec->hash1 and
27ea6c34e9d8a914b0aeebe9ca98eb65dea404d0Lukas Slebodnik * rec->has2 are the same. (It is not very likely).
27ea6c34e9d8a914b0aeebe9ca98eb65dea404d0Lukas Slebodnik */
27ea6c34e9d8a914b0aeebe9ca98eb65dea404d0Lukas Slebodnik return;
27ea6c34e9d8a914b0aeebe9ca98eb65dea404d0Lukas Slebodnik }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (cur == rec) {
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik mcc->hash_table[hash] = sss_mc_next_slot_with_hash(rec, hash);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce } else {
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik slot = sss_mc_next_slot_with_hash(cur, hash);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce while (slot != MC_INVALID_VAL) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce prev = cur;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (cur == rec) {
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik slot = sss_mc_next_slot_with_hash(cur, hash);
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik sss_mc_chain_slot_to_record_with_hash(prev, hash, slot);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce slot = MC_INVALID_VAL;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce } else {
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik slot = sss_mc_next_slot_with_hash(cur, hash);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce}
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorcestatic void sss_mc_free_slots(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec)
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce{
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce uint32_t slot;
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce uint32_t num;
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce uint32_t i;
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce slot = MC_PTR_TO_SLOT(mcc->data_table, rec);
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce num = MC_SIZE_TO_SLOTS(rec->len);
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce for (i = 0; i < num; i++) {
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce MC_CLEAR_BIT(mcc->free_table, slot + i);
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce }
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce}
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorcestatic void sss_mc_invalidate_rec(struct sss_mc_ctx *mcc,
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce struct sss_mc_rec *rec)
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce{
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (rec->b1 == MC_INVALID_VAL) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* record already invalid */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce return;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce /* Remove from hash chains */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* hash chain 1 */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce sss_mc_rm_rec_from_chain(mcc, rec, rec->hash1);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* hash chain 2 */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce sss_mc_rm_rec_from_chain(mcc, rec, rec->hash2);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce /* Clear from free_table */
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce sss_mc_free_slots(mcc, rec);
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce /* Invalidate record fields */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce MC_RAISE_INVALID_BARRIER(rec);
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce memset(rec->data, MC_INVALID_VAL8, ((MC_SLOT_SIZE * MC_SIZE_TO_SLOTS(rec->len))
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce - sizeof(struct sss_mc_rec)));
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce rec->len = MC_INVALID_VAL32;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce rec->expire = MC_INVALID_VAL64;
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik rec->next1 = MC_INVALID_VAL32;
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik rec->next2 = MC_INVALID_VAL32;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce rec->hash1 = MC_INVALID_VAL32;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce rec->hash2 = MC_INVALID_VAL32;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce MC_LOWER_BARRIER(rec);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce}
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorcestatic bool sss_mc_is_valid_rec(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec)
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce{
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce struct sss_mc_rec *self;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce uint32_t slot;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce if (((uint8_t *)rec < mcc->data_table) ||
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce ((uint8_t *)rec > (mcc->data_table + mcc->dt_size - MC_SLOT_SIZE))) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return false;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce if ((rec->b1 == MC_INVALID_VAL) ||
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce (rec->b1 != rec->b2)) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return false;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce
31c47cacc7f9453153e57319474909d23122883fPavel Březina if (!MC_CHECK_RECORD_LENGTH(mcc, rec)) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return false;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce if (rec->expire == MC_INVALID_VAL64) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return false;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik /* next record can be invalid if there are no next records */
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce if (rec->hash1 == MC_INVALID_VAL32) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return false;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce } else {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce self = NULL;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce slot = mcc->hash_table[rec->hash1];
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce while (slot != MC_INVALID_VAL32 && self != rec) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce self = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik slot = sss_mc_next_slot_with_hash(self, rec->hash1);
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce if (self != rec) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return false;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce if (rec->hash2 != MC_INVALID_VAL32) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce self = NULL;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce slot = mcc->hash_table[rec->hash2];
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce while (slot != MC_INVALID_VAL32 && self != rec) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce self = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik slot = sss_mc_next_slot_with_hash(self, rec->hash2);
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce if (self != rec) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return false;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce /* all tests passed */
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return true;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce}
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce/* FIXME: This is a very simplistic, inefficient, memory allocator,
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce * it will just free the oldest entries regardless of expiration if it
677a31351c80453d9ce006481364399a96312052René Genz * cycled the whole free bits map and found no empty slot */
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorcestatic errno_t sss_mc_find_free_slots(struct sss_mc_ctx *mcc,
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce int num_slots, uint32_t *free_slot)
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce{
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce struct sss_mc_rec *rec;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t tot_slots;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t cur;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t i;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t t;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce bool used;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce tot_slots = mcc->ft_size * 8;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce /* Try to find a free slot w/o removing anything first */
677a31351c80453d9ce006481364399a96312052René Genz /* FIXME: Is it really worth it? Maybe it is easier to
677a31351c80453d9ce006481364399a96312052René Genz * just recycle the next set of slots? */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if ((mcc->next_slot + num_slots) > tot_slots) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce cur = 0;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce } else {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce cur = mcc->next_slot;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* search for enough (num_slots) consecutive zero bits, indicating
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce * consecutive empty slots */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce for (i = 0; i < mcc->ft_size; i++) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce t = cur / 8;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* if all full in this byte skip directly to the next */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (mcc->free_table[t] == 0xff) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce cur = ((cur + 8) & ~7);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (cur >= tot_slots) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce cur = 0;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce continue;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* at least one bit in this byte is marked as empty */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce for (t = ((cur + 8) & ~7) ; cur < t; cur++) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce MC_PROBE_BIT(mcc->free_table, cur, used);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (!used) break;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* check if we have enough slots before hitting the table end */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if ((cur + num_slots) > tot_slots) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce cur = 0;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce continue;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* check if we have at least num_slots empty starting from the first
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce * we found in the previous steps */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce for (t = cur + num_slots; cur < t; cur++) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce MC_PROBE_BIT(mcc->free_table, cur, used);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (used) break;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (cur == t) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* ok found num_slots consecutive free bits */
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce *free_slot = cur - num_slots;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return EOK;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* no free slots found, free occupied slots after next_slot */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if ((mcc->next_slot + num_slots) > tot_slots) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce cur = 0;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce } else {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce cur = mcc->next_slot;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce for (i = 0; i < num_slots; i++) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce MC_PROBE_BIT(mcc->free_table, cur + i, used);
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce if (used) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce /* the first used slot should be a record header, however we
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce * carefully check it is a valid header and hardfail if not */
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce rec = MC_SLOT_TO_PTR(mcc->data_table, cur + i, struct sss_mc_rec);
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce if (!sss_mc_is_valid_rec(mcc, rec)) {
677a31351c80453d9ce006481364399a96312052René Genz /* this is a fatal error, the caller should probably just
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce * invalidate the whole cache */
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return EFAULT;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce /* next loop skip the whole record */
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce i += MC_SIZE_TO_SLOTS(rec->len) - 1;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce /* finally invalidate record completely */
da4c23b6670adb45f71cf51aaeca8df30c2144beSimo Sorce sss_mc_invalidate_rec(mcc, rec);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce mcc->next_slot = cur + num_slots;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce *free_slot = cur;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return EOK;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce}
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidekstatic errno_t sss_mc_get_strs_offset(struct sss_mc_ctx *mcc,
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek size_t *_offset)
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek{
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek switch (mcc->type) {
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek case SSS_MC_PASSWD:
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek *_offset = offsetof(struct sss_mc_pwd_data, strs);
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek return EOK;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek case SSS_MC_GROUP:
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek *_offset = offsetof(struct sss_mc_grp_data, strs);
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek return EOK;
225dc6914cdc8920b02a129b98ece1ed97b99c03Lukas Slebodnik case SSS_MC_INITGROUPS:
225dc6914cdc8920b02a129b98ece1ed97b99c03Lukas Slebodnik *_offset = offsetof(struct sss_mc_initgr_data, gids);
225dc6914cdc8920b02a129b98ece1ed97b99c03Lukas Slebodnik return EOK;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek default:
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE, "Unknown memory cache type.\n");
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek return EINVAL;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek }
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek}
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidekstatic errno_t sss_mc_get_strs_len(struct sss_mc_ctx *mcc,
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek struct sss_mc_rec *rec,
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek size_t *_len)
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek{
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek switch (mcc->type) {
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek case SSS_MC_PASSWD:
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek *_len = ((struct sss_mc_pwd_data *)&rec->data)->strs_len;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek return EOK;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek case SSS_MC_GROUP:
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek *_len = ((struct sss_mc_grp_data *)&rec->data)->strs_len;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek return EOK;
225dc6914cdc8920b02a129b98ece1ed97b99c03Lukas Slebodnik case SSS_MC_INITGROUPS:
225dc6914cdc8920b02a129b98ece1ed97b99c03Lukas Slebodnik *_len = ((struct sss_mc_initgr_data *)&rec->data)->data_len;
225dc6914cdc8920b02a129b98ece1ed97b99c03Lukas Slebodnik return EOK;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek default:
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE, "Unknown memory cache type.\n");
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek return EINVAL;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek }
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek}
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorcestatic struct sss_mc_rec *sss_mc_find_record(struct sss_mc_ctx *mcc,
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce struct sized_string *key)
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce{
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce struct sss_mc_rec *rec;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t hash;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t slot;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce rel_ptr_t name_ptr;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce char *t_key;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek size_t strs_offset;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek size_t strs_len;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek uint8_t *max_addr;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek errno_t ret;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce hash = sss_mc_hash(mcc, key->str, key->len);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce slot = mcc->hash_table[hash];
13df7b9e400211c717284fb841c849ba034ed348Michal Zidek if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce return NULL;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek /* Get max address of data table. */
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek max_addr = mcc->data_table + mcc->dt_size;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek ret = sss_mc_get_strs_offset(mcc, &strs_offset);
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek if (ret != EOK) {
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek return NULL;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek }
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce while (slot != MC_INVALID_VAL) {
13df7b9e400211c717284fb841c849ba034ed348Michal Zidek if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek DEBUG(SSSDBG_FATAL_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Corrupted fastcache. Slot number too big.\n");
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek sss_mc_save_corrupted(mcc);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek sss_mmap_cache_reset(mcc);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek return NULL;
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek }
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce rec = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek ret = sss_mc_get_strs_len(mcc, rec, &strs_len);
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek if (ret != EOK) {
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek return NULL;
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek }
441e6050f4b67134d15862e401b4c4e8546d7387Michal Zidek
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose if (key->len > strs_len) {
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose /* The string cannot be in current record */
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose slot = sss_mc_next_slot_with_hash(rec, hash);
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose continue;
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose }
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose
d8057ec487e452038f0106042021fa612bbb8555Michal Zidek safealign_memcpy(&name_ptr, rec->data, sizeof(rel_ptr_t), NULL);
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose t_key = (char *)rec->data + name_ptr;
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose /* name_ptr must point to some data in the strs/gids area of the data
677a31351c80453d9ce006481364399a96312052René Genz * payload. Since it is a pointer relative to rec->data it must be
677a31351c80453d9ce006481364399a96312052René Genz * larger/equal to strs_offset and must be smaller then strs_offset + strs_len.
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose * Additionally the area must not end outside of the data table and
677a31351c80453d9ce006481364399a96312052René Genz * t_key must be a zero-terminated string. */
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose if (name_ptr < strs_offset
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose || name_ptr >= strs_offset + strs_len
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose || (uint8_t *)rec->data > max_addr
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose || strs_offset > max_addr - (uint8_t *)rec->data
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose || strs_len > max_addr - (uint8_t *)rec->data - strs_offset) {
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek DEBUG(SSSDBG_FATAL_FAILURE,
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose "Corrupted fastcache entry at slot %u. "
4382047490dd4f80b407cc1e618da048f13e5f8fSumit Bose "name_ptr value is %u.\n", slot, name_ptr);
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek sss_mc_save_corrupted(mcc);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek sss_mmap_cache_reset(mcc);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek return NULL;
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (strcmp(key->str, t_key) == 0) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce break;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik slot = sss_mc_next_slot_with_hash(rec, hash);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (slot == MC_INVALID_VAL) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce return NULL;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce return rec;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce}
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorcestatic errno_t sss_mc_get_record(struct sss_mc_ctx **_mcc,
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce size_t rec_len,
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce struct sized_string *key,
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce struct sss_mc_rec **_rec)
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce{
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce struct sss_mc_ctx *mcc = *_mcc;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce struct sss_mc_rec *old_rec = NULL;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce struct sss_mc_rec *rec;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce int old_slots;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce int num_slots;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce uint32_t base_slot;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce errno_t ret;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce int i;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce num_slots = MC_SIZE_TO_SLOTS(rec_len);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce old_rec = sss_mc_find_record(mcc, key);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (old_rec) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce old_slots = MC_SIZE_TO_SLOTS(old_rec->len);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce if (old_slots == num_slots) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce *_rec = old_rec;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return EOK;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* slot size changed, invalidate record and fall through to get a
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce * fully new record */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce sss_mc_invalidate_rec(mcc, old_rec);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* we are going to use more space, find enough free slots */
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce ret = sss_mc_find_free_slots(mcc, num_slots, &base_slot);
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce if (ret != EOK) {
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce if (ret == EFAULT) {
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Fatal internal mmap cache error, invalidating cache!\n");
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce (void)sss_mmap_cache_reinit(talloc_parent(mcc), -1, -1, _mcc);
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce }
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return ret;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce rec = MC_SLOT_TO_PTR(mcc->data_table, base_slot, struct sss_mc_rec);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* mark as not valid yet */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce MC_RAISE_INVALID_BARRIER(rec);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce rec->len = rec_len;
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik rec->next1 = MC_INVALID_VAL;
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik rec->next2 = MC_INVALID_VAL;
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik rec->padding = MC_INVALID_VAL;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce MC_LOWER_BARRIER(rec);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce /* and now mark slots as used */
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce for (i = 0; i < num_slots; i++) {
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce MC_SET_BIT(mcc->free_table, base_slot + i);
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce }
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce *_rec = rec;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return EOK;
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce}
24451a6231ea0b7fd0e98a9931e8254aa17bf4cfSimo Sorce
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorcestatic inline void sss_mmap_set_rec_header(struct sss_mc_ctx *mcc,
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce struct sss_mc_rec *rec,
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce size_t len, int ttl,
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce const char *key1, size_t key1_len,
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce const char *key2, size_t key2_len)
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce{
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce rec->len = len;
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce rec->expire = time(NULL) + ttl;
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce rec->hash1 = sss_mc_hash(mcc, key1, key1_len);
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce rec->hash2 = sss_mc_hash(mcc, key2, key2_len);
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce}
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorcestatic inline void sss_mmap_chain_in_rec(struct sss_mc_ctx *mcc,
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce struct sss_mc_rec *rec)
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce{
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce /* name first */
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce sss_mc_add_rec_to_chain(mcc, rec, rec->hash1);
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce /* then uid/gid */
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce sss_mc_add_rec_to_chain(mcc, rec, rec->hash2);
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce}
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce/***************************************************************************
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce * generic invalidation
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce ***************************************************************************/
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorcestatic errno_t sss_mmap_cache_invalidate(struct sss_mc_ctx *mcc,
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce struct sized_string *key)
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce{
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce struct sss_mc_rec *rec;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce if (mcc == NULL) {
677a31351c80453d9ce006481364399a96312052René Genz /* cache not initialized? */
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce return EINVAL;
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce }
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce rec = sss_mc_find_record(mcc, key);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce if (rec == NULL) {
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce /* nothing to invalidate */
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce return ENOENT;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce }
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce sss_mc_invalidate_rec(mcc, rec);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce return EOK;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce}
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce/***************************************************************************
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce * passwd map
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce ***************************************************************************/
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorceerrno_t sss_mmap_cache_pw_store(struct sss_mc_ctx **_mcc,
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce struct sized_string *name,
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce struct sized_string *pw,
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce uid_t uid, gid_t gid,
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce struct sized_string *gecos,
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce struct sized_string *homedir,
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce struct sized_string *shell)
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce{
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce struct sss_mc_ctx *mcc = *_mcc;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce struct sss_mc_rec *rec;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce struct sss_mc_pwd_data *data;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce struct sized_string uidkey;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce char uidstr[11];
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce size_t data_len;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce size_t rec_len;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce size_t pos;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce int ret;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce if (mcc == NULL) {
677a31351c80453d9ce006481364399a96312052René Genz /* cache not initialized? */
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce return EINVAL;
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce }
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce ret = snprintf(uidstr, 11, "%ld", (long)uid);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce if (ret > 10) {
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce return EINVAL;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce }
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce to_sized_string(&uidkey, uidstr);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce data_len = name->len + pw->len + gecos->len + homedir->len + shell->len;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce rec_len = sizeof(struct sss_mc_rec) +
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce sizeof(struct sss_mc_pwd_data) +
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce data_len;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce if (rec_len > mcc->dt_size) {
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce return ENOMEM;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce }
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce ret = sss_mc_get_record(_mcc, rec_len, name, &rec);
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce if (ret != EOK) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return ret;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce data = (struct sss_mc_pwd_data *)rec->data;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce pos = 0;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce MC_RAISE_BARRIER(rec);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce /* header */
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce sss_mmap_set_rec_header(mcc, rec, rec_len, mcc->valid_time_slot,
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce name->str, name->len, uidkey.str, uidkey.len);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce /* passwd struct */
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce data->name = MC_PTR_DIFF(data->strs, data);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce data->uid = uid;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce data->gid = gid;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce data->strs_len = data_len;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce memcpy(&data->strs[pos], name->str, name->len);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce pos += name->len;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce memcpy(&data->strs[pos], pw->str, pw->len);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce pos += pw->len;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce memcpy(&data->strs[pos], gecos->str, gecos->len);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce pos += gecos->len;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce memcpy(&data->strs[pos], homedir->str, homedir->len);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce pos += homedir->len;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce memcpy(&data->strs[pos], shell->str, shell->len);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce pos += shell->len;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce MC_LOWER_BARRIER(rec);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce /* finally chain the rec in the hash table */
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce sss_mmap_chain_in_rec(mcc, rec);
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce return EOK;
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce}
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorceerrno_t sss_mmap_cache_pw_invalidate(struct sss_mc_ctx *mcc,
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce struct sized_string *name)
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce{
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce return sss_mmap_cache_invalidate(mcc, name);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce}
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorceerrno_t sss_mmap_cache_pw_invalidate_uid(struct sss_mc_ctx *mcc, uid_t uid)
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce{
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce struct sss_mc_rec *rec;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce struct sss_mc_pwd_data *data;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce uint32_t hash;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce uint32_t slot;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce char *uidstr;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce errno_t ret;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce if (mcc == NULL) {
677a31351c80453d9ce006481364399a96312052René Genz /* cache not initialized? */
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce return EINVAL;
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce }
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce uidstr = talloc_asprintf(NULL, "%ld", (long)uid);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce if (!uidstr) {
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce return ENOMEM;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce }
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce hash = sss_mc_hash(mcc, uidstr, strlen(uidstr) + 1);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce slot = mcc->hash_table[hash];
13df7b9e400211c717284fb841c849ba034ed348Michal Zidek if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce ret = ENOENT;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce goto done;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce }
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce while (slot != MC_INVALID_VAL) {
13df7b9e400211c717284fb841c849ba034ed348Michal Zidek if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE, "Corrupted fastcache.\n");
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek sss_mc_save_corrupted(mcc);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek sss_mmap_cache_reset(mcc);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek ret = ENOENT;
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek goto done;
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek }
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce rec = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce data = (struct sss_mc_pwd_data *)(&rec->data);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce if (uid == data->uid) {
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce break;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce }
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik slot = sss_mc_next_slot_with_hash(rec, hash);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce }
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce if (slot == MC_INVALID_VAL) {
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce ret = ENOENT;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce goto done;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce }
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce sss_mc_invalidate_rec(mcc, rec);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce ret = EOK;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorcedone:
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce talloc_zfree(uidstr);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce return ret;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce}
6cb1a6e7c7517ab4ccb8ad37ade86f95b5c16a01Simo Sorce
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce/***************************************************************************
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce * group map
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce ***************************************************************************/
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorceint sss_mmap_cache_gr_store(struct sss_mc_ctx **_mcc,
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce struct sized_string *name,
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce struct sized_string *pw,
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce gid_t gid, size_t memnum,
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce char *membuf, size_t memsize)
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce{
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce struct sss_mc_ctx *mcc = *_mcc;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce struct sss_mc_rec *rec;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce struct sss_mc_grp_data *data;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce struct sized_string gidkey;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce char gidstr[11];
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce size_t data_len;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce size_t rec_len;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce size_t pos;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce int ret;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce if (mcc == NULL) {
677a31351c80453d9ce006481364399a96312052René Genz /* cache not initialized? */
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce return EINVAL;
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce }
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce ret = snprintf(gidstr, 11, "%ld", (long)gid);
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce if (ret > 10) {
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce return EINVAL;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce }
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce to_sized_string(&gidkey, gidstr);
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce data_len = name->len + pw->len + memsize;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce rec_len = sizeof(struct sss_mc_rec) +
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce sizeof(struct sss_mc_grp_data) +
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce data_len;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce if (rec_len > mcc->dt_size) {
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce return ENOMEM;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce }
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce ret = sss_mc_get_record(_mcc, rec_len, name, &rec);
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce if (ret != EOK) {
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce return ret;
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce }
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce data = (struct sss_mc_grp_data *)rec->data;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce pos = 0;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce MC_RAISE_BARRIER(rec);
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce /* header */
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce sss_mmap_set_rec_header(mcc, rec, rec_len, mcc->valid_time_slot,
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce name->str, name->len, gidkey.str, gidkey.len);
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce /* group struct */
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce data->name = MC_PTR_DIFF(data->strs, data);
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce data->gid = gid;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce data->members = memnum;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce data->strs_len = data_len;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce memcpy(&data->strs[pos], name->str, name->len);
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce pos += name->len;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce memcpy(&data->strs[pos], pw->str, pw->len);
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce pos += pw->len;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce memcpy(&data->strs[pos], membuf, memsize);
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce pos += memsize;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce MC_LOWER_BARRIER(rec);
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce /* finally chain the rec in the hash table */
b294d4c50ec4431bc07ad7ec5a73e8af0e53c54fSimo Sorce sss_mmap_chain_in_rec(mcc, rec);
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce return EOK;
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce}
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorceerrno_t sss_mmap_cache_gr_invalidate(struct sss_mc_ctx *mcc,
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce struct sized_string *name)
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce{
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce return sss_mmap_cache_invalidate(mcc, name);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce}
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorceerrno_t sss_mmap_cache_gr_invalidate_gid(struct sss_mc_ctx *mcc, gid_t gid)
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce{
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce struct sss_mc_rec *rec;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce struct sss_mc_grp_data *data;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce uint32_t hash;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce uint32_t slot;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce char *gidstr;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce errno_t ret;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce if (mcc == NULL) {
677a31351c80453d9ce006481364399a96312052René Genz /* cache not initialized? */
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce return EINVAL;
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce }
270fcd0ad214d490b6b8e278cdbafda1fb7f9d8fSimo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce gidstr = talloc_asprintf(NULL, "%ld", (long)gid);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce if (!gidstr) {
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce return ENOMEM;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce }
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce hash = sss_mc_hash(mcc, gidstr, strlen(gidstr) + 1);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce slot = mcc->hash_table[hash];
13df7b9e400211c717284fb841c849ba034ed348Michal Zidek if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce ret = ENOENT;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce goto done;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce }
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce while (slot != MC_INVALID_VAL) {
13df7b9e400211c717284fb841c849ba034ed348Michal Zidek if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE, "Corrupted fastcache.\n");
f9091077bfbb09f052d08e25ac5e00af0baa6dfbMichal Zidek sss_mc_save_corrupted(mcc);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek sss_mmap_cache_reset(mcc);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek ret = ENOENT;
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek goto done;
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek }
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce rec = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce data = (struct sss_mc_grp_data *)(&rec->data);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce if (gid == data->gid) {
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce break;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce }
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
581de96fc30b7fe44070f17a8a73f3374d38d6ffLukas Slebodnik slot = sss_mc_next_slot_with_hash(rec, hash);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce }
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce if (slot == MC_INVALID_VAL) {
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce ret = ENOENT;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce goto done;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce }
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce sss_mc_invalidate_rec(mcc, rec);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce ret = EOK;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorcedone:
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce talloc_zfree(gidstr);
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce return ret;
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce}
8088274b2389b76f4be581736e55f26a8322fad1Simo Sorce
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnikerrno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik struct sized_string *name,
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik struct sized_string *unique_name,
39b31427e2d11ca318df11fd48db33a7cc610aa7Lukas Slebodnik uint32_t num_groups,
39b31427e2d11ca318df11fd48db33a7cc610aa7Lukas Slebodnik uint8_t *gids_buf)
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik{
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik struct sss_mc_ctx *mcc = *_mcc;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik struct sss_mc_rec *rec;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik struct sss_mc_initgr_data *data;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik size_t data_len;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik size_t rec_len;
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik size_t pos;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik int ret;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik if (mcc == NULL) {
677a31351c80453d9ce006481364399a96312052René Genz /* cache not initialized? */
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik return EINVAL;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik }
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik /* array of gids + name + unique_name */
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik data_len = num_groups * sizeof(uint32_t) + name->len + unique_name->len;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik rec_len = sizeof(struct sss_mc_rec) + sizeof(struct sss_mc_initgr_data)
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik + data_len;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik if (rec_len > mcc->dt_size) {
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik return ENOMEM;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik }
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik /* use unique name for searching potential old records */
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik ret = sss_mc_get_record(_mcc, rec_len, unique_name, &rec);
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik if (ret != EOK) {
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik return ret;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik }
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik data = (struct sss_mc_initgr_data *)rec->data;
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik pos = 0;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik MC_RAISE_BARRIER(rec);
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik
677a31351c80453d9ce006481364399a96312052René Genz /* We cannot use two keys for searching in initgroups cache.
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik * Use the first key twice.
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik */
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik sss_mmap_set_rec_header(mcc, rec, rec_len, mcc->valid_time_slot,
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik name->str, name->len,
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik unique_name->str, unique_name->len);
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik /* initgroups struct */
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik data->strs_len = name->len + unique_name->len;
225dc6914cdc8920b02a129b98ece1ed97b99c03Lukas Slebodnik data->data_len = data_len;
39b31427e2d11ca318df11fd48db33a7cc610aa7Lukas Slebodnik data->num_groups = num_groups;
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik memcpy((char *)data->gids + pos, gids_buf, num_groups * sizeof(uint32_t));
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik pos += num_groups * sizeof(uint32_t);
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik memcpy((char *)data->gids + pos, unique_name->str, unique_name->len);
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik data->strs = data->unique_name = MC_PTR_DIFF((char *)data->gids + pos, data);
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik pos += unique_name->len;
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik memcpy((char *)data->gids + pos, name->str, name->len);
dda0258705de7255e6ec54b7f9adbde83a220996Lukas Slebodnik data->name = MC_PTR_DIFF((char *)data->gids + pos, data);
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik MC_LOWER_BARRIER(rec);
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik /* finally chain the rec in the hash table */
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik sss_mmap_chain_in_rec(mcc, rec);
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik return EOK;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik}
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnikerrno_t sss_mmap_cache_initgr_invalidate(struct sss_mc_ctx *mcc,
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik struct sized_string *name)
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik{
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik return sss_mmap_cache_invalidate(mcc, name);
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik}
c3ef027218fe9a7d16a70ca9d2f53e3d995e369fSimo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce/***************************************************************************
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce * initialization
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ***************************************************************************/
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
714ba5f50551a42df324714358dc379b351d4a53Michal Zidek/* Copy of sss_mc_set_recycled is present in the src/tools/tools_mc_util.c.
714ba5f50551a42df324714358dc379b351d4a53Michal Zidek * If you modify this function, you should modify the duplicated function
714ba5f50551a42df324714358dc379b351d4a53Michal Zidek * too. */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorcestatic errno_t sss_mc_set_recycled(int fd)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce{
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce uint32_t w = SSS_MC_HEADER_RECYCLED;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce struct sss_mc_header h;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce off_t offset;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce off_t pos;
8e44ddfccebe61728d8a2c1dafce36dfa944bc90Jakub Hrozek ssize_t written;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce offset = MC_PTR_DIFF(&h.status, &h);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce pos = lseek(fd, offset, SEEK_SET);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce if (pos == -1) {
677a31351c80453d9ce006481364399a96312052René Genz /* What do we do now? */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce return errno;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozek
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozek errno = 0;
8e44ddfccebe61728d8a2c1dafce36dfa944bc90Jakub Hrozek written = sss_atomic_write_s(fd, (uint8_t *)&w, sizeof(h.status));
8e44ddfccebe61728d8a2c1dafce36dfa944bc90Jakub Hrozek if (written == -1) {
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozek return errno;
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozek }
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozek
8e44ddfccebe61728d8a2c1dafce36dfa944bc90Jakub Hrozek if (written != sizeof(h.status)) {
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozek /* Write error */
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozek return EIO;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce return EOK;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce}
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce/*
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce * When we (re)create a new file we must mark the current file as recycled
677a31351c80453d9ce006481364399a96312052René Genz * so active clients will abandon its use ASAP.
677a31351c80453d9ce006481364399a96312052René Genz * We unlink the current file and make a new one.
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorcestatic errno_t sss_mc_create_file(struct sss_mc_ctx *mc_ctx)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce{
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mode_t old_mask;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce int ofd;
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek int ret, uret;
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek useconds_t t = 50000;
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek int retries = 3;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ofd = open(mc_ctx->file, O_RDWR);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce if (ofd != -1) {
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek ret = sss_br_lock_file(ofd, 0, 1, retries, t);
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek if (ret != EOK) {
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek DEBUG(SSSDBG_FATAL_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Failed to lock file %s.\n", mc_ctx->file);
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ret = sss_mc_set_recycled(ofd);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce if (ret) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE, "Failed to mark mmap file %s as"
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek " recycled: %d(%s)\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov mc_ctx->file, ret, strerror(ret));
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce close(ofd);
4eaa0cb982a58088680f974429b48ddf23b5825eMichal Zidek } else if (errno != ENOENT) {
4eaa0cb982a58088680f974429b48ddf23b5825eMichal Zidek ret = errno;
4eaa0cb982a58088680f974429b48ddf23b5825eMichal Zidek DEBUG(SSSDBG_CRIT_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Failed to open old memory cache file %s: %d(%s).\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov mc_ctx->file, ret, strerror(ret));
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
0d3bd5e0dbdd7579b64cec0b0e93605a3c37cdc1Stephen Gallagher errno = 0;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ret = unlink(mc_ctx->file);
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek if (ret == -1 && errno != ENOENT) {
0d3bd5e0dbdd7579b64cec0b0e93605a3c37cdc1Stephen Gallagher ret = errno;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Failed to rm mmap file %s: %d(%s)\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov mc_ctx->file, ret, strerror(ret));
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce /* temporarily relax umask as we need the file to be readable
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce * by everyone for now */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce old_mask = umask(0022);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek errno = 0;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->fd = open(mc_ctx->file, O_CREAT | O_EXCL | O_RDWR, 0644);
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek umask(old_mask);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce if (mc_ctx->fd == -1) {
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ret = errno;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Failed to open mmap file %s: %d(%s)\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov mc_ctx->file, ret, strerror(ret));
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek return ret;
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek }
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek ret = sss_br_lock_file(mc_ctx->fd, 0, 1, retries, t);
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek if (ret != EOK) {
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek DEBUG(SSSDBG_FATAL_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Failed to lock file %s.\n", mc_ctx->file);
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek close(mc_ctx->fd);
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek mc_ctx->fd = -1;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek /* Report on unlink failures but don't overwrite the errno
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek * from sss_br_lock_file
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek */
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek errno = 0;
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek uret = unlink(mc_ctx->file);
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek if (uret == -1) {
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek uret = errno;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Failed to rm mmap file %s: %d(%s)\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov mc_ctx->file, uret, strerror(uret));
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
8b7040df8bcfee8cb31903136562eea73232f3d0Jakub Hrozek return ret;
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek }
33cbb789ff71be5dccbb4a0acd68814b0d53da34Michal Zidek
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce return ret;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce}
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorcestatic void sss_mc_header_update(struct sss_mc_ctx *mc_ctx, int status)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce{
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce struct sss_mc_header *h;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce /* update header using barriers */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h = (struct sss_mc_header *)mc_ctx->mmap_base;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce MC_RAISE_BARRIER(h);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek if (status == SSS_MC_HEADER_ALIVE) {
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek /* no reason to update anything else if the file is recycled or
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek * right before reset */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h->hash_table = MC_PTR_DIFF(mc_ctx->hash_table, mc_ctx->mmap_base);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h->free_table = MC_PTR_DIFF(mc_ctx->free_table, mc_ctx->mmap_base);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h->data_table = MC_PTR_DIFF(mc_ctx->data_table, mc_ctx->mmap_base);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h->ht_size = mc_ctx->ht_size;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h->ft_size = mc_ctx->ft_size;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h->dt_size = mc_ctx->dt_size;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h->major_vno = SSS_MC_MAJOR_VNO;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h->minor_vno = SSS_MC_MINOR_VNO;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h->seed = mc_ctx->seed;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h->reserved = 0;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce h->status = status;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce MC_LOWER_BARRIER(h);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce}
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidekstatic int mc_ctx_destructor(struct sss_mc_ctx *mc_ctx)
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek{
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek int ret;
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek /* Print debug message to logs if munmap() or close()
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek * fail but always return 0 */
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek if (mc_ctx->mmap_base != NULL) {
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek ret = munmap(mc_ctx->mmap_base, mc_ctx->mmap_size);
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek if (ret == -1) {
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek ret = errno;
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek DEBUG(SSSDBG_CRIT_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Failed to unmap old memory cache file."
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "[%d]: %s\n", ret, strerror(ret));
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek }
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek }
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek if (mc_ctx->fd != -1) {
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek ret = close(mc_ctx->fd);
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek if (ret == -1) {
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek ret = errno;
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek DEBUG(SSSDBG_CRIT_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Failed to close old memory cache file."
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "[%d]: %s\n", ret, strerror(ret));
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek }
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek }
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek return 0;
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek}
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorceerrno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name,
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce enum sss_mc_type type, size_t n_elem,
e9f08ebaba5ec61af74c112f50c7d66257998c97Jan Zeleny time_t timeout, struct sss_mc_ctx **mcc)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce{
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce struct sss_mc_ctx *mc_ctx = NULL;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce unsigned int rseed;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce int payload;
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek int ret, dret;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce switch (type) {
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce case SSS_MC_PASSWD:
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce payload = SSS_AVG_PASSWD_PAYLOAD;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce break;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce case SSS_MC_GROUP:
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce payload = SSS_AVG_GROUP_PAYLOAD;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce break;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik case SSS_MC_INITGROUPS:
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik payload = SSS_AVG_INITGROUP_PAYLOAD;
ebf6735dd4f71bf3dc9105e5d04d11e744c64a59Lukas Slebodnik break;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce default:
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce return EINVAL;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx = talloc_zero(mem_ctx, struct sss_mc_ctx);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce if (!mc_ctx) {
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce return ENOMEM;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->fd = -1;
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek talloc_set_destructor(mc_ctx, mc_ctx_destructor);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce mc_ctx->name = talloc_strdup(mc_ctx, name);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce if (!mc_ctx->name) {
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ret = ENOMEM;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce goto done;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->type = type;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
e9f08ebaba5ec61af74c112f50c7d66257998c97Jan Zeleny mc_ctx->valid_time_slot = timeout;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->file = talloc_asprintf(mc_ctx, "%s/%s",
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce SSS_NSS_MCACHE_DIR, name);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce if (!mc_ctx->file) {
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ret = ENOMEM;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce goto done;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce /* elements must always be multiple of 8 to make things easier to handle,
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce * so we increase by the necessary amount if they are not a multiple */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce /* We can use MC_ALIGN64 for this */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce n_elem = MC_ALIGN64(n_elem);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce /* hash table is double the size because it will store both forward and
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce * reverse keys (name/uid, name/gid, ..) */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->ht_size = MC_HT_SIZE(n_elem * 2);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->dt_size = MC_DT_SIZE(n_elem, payload);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->ft_size = MC_FT_SIZE(n_elem);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->mmap_size = MC_HEADER_SIZE +
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce MC_ALIGN64(mc_ctx->dt_size) +
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce MC_ALIGN64(mc_ctx->ft_size) +
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce MC_ALIGN64(mc_ctx->ht_size);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce /* for now ALWAYS create a new file on restart */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ret = sss_mc_create_file(mc_ctx);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce if (ret) {
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce goto done;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ret = ftruncate(mc_ctx->fd, mc_ctx->mmap_size);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce if (ret == -1) {
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ret = errno;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Failed to resize file %s: %d(%s)\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov mc_ctx->file, ret, strerror(ret));
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce goto done;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->mmap_base = mmap(NULL, mc_ctx->mmap_size,
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce PROT_READ | PROT_WRITE,
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce MAP_SHARED, mc_ctx->fd, 0);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce if (mc_ctx->mmap_base == MAP_FAILED) {
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ret = errno;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Failed to mmap file %s(%zu): %d(%s)\n",
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->file, mc_ctx->mmap_size,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov ret, strerror(ret));
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce goto done;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->data_table = MC_PTR_ADD(mc_ctx->mmap_base, MC_HEADER_SIZE);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->free_table = MC_PTR_ADD(mc_ctx->data_table,
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce MC_ALIGN64(mc_ctx->dt_size));
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->hash_table = MC_PTR_ADD(mc_ctx->free_table,
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce MC_ALIGN64(mc_ctx->ft_size));
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
6acf7c92ab38ad388295b2d57cc97c4598aa95ccSimo Sorce memset(mc_ctx->data_table, 0xff, mc_ctx->dt_size);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce memset(mc_ctx->free_table, 0x00, mc_ctx->ft_size);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce memset(mc_ctx->hash_table, 0xff, mc_ctx->ht_size);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce /* generate a pseudo-random seed.
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce * Needed to fend off dictionary based collision attacks */
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce rseed = time(NULL) * getpid();
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce mc_ctx->seed = rand_r(&rseed);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce sss_mc_header_update(mc_ctx, SSS_MC_HEADER_ALIVE);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce ret = EOK;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorcedone:
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce if (ret) {
677a31351c80453d9ce006481364399a96312052René Genz /* Closing the file descriptor and unmapping the file
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek * from memory is done in the mc_ctx_destructor. */
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek if (mc_ctx && mc_ctx->file && mc_ctx->fd != -1) {
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek dret = unlink(mc_ctx->file);
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek if (dret == -1) {
8e09148b68a3fd8b06fcb746054f3cfa250b40f8Michal Zidek dret = errno;
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek DEBUG(SSSDBG_CRIT_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Failed to rm mmap file %s: %d(%s)\n", mc_ctx->file,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov dret, strerror(dret));
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce talloc_free(mc_ctx);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce } else {
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce *mcc = mc_ctx;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce return ret;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce}
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce
99c99e557020775714f028b28a147edda290c783Michal Zidekerrno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem,
99c99e557020775714f028b28a147edda290c783Michal Zidek time_t timeout, struct sss_mc_ctx **mc_ctx)
99c99e557020775714f028b28a147edda290c783Michal Zidek{
99c99e557020775714f028b28a147edda290c783Michal Zidek errno_t ret;
99c99e557020775714f028b28a147edda290c783Michal Zidek TALLOC_CTX* tmp_ctx = NULL;
99c99e557020775714f028b28a147edda290c783Michal Zidek char *name;
99c99e557020775714f028b28a147edda290c783Michal Zidek enum sss_mc_type type;
99c99e557020775714f028b28a147edda290c783Michal Zidek
99c99e557020775714f028b28a147edda290c783Michal Zidek if (mc_ctx == NULL || (*mc_ctx) == NULL) {
99c99e557020775714f028b28a147edda290c783Michal Zidek DEBUG(SSSDBG_CRIT_FAILURE,
42604cc8d11743febf5aa892cb3a7d3c32bfed48Lukas Slebodnik "Unable to re-init uninitialized memory cache.\n");
99c99e557020775714f028b28a147edda290c783Michal Zidek return EINVAL;
99c99e557020775714f028b28a147edda290c783Michal Zidek }
99c99e557020775714f028b28a147edda290c783Michal Zidek
99c99e557020775714f028b28a147edda290c783Michal Zidek tmp_ctx = talloc_new(NULL);
99c99e557020775714f028b28a147edda290c783Michal Zidek if (tmp_ctx == NULL) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory.\n");
99c99e557020775714f028b28a147edda290c783Michal Zidek return ENOMEM;
99c99e557020775714f028b28a147edda290c783Michal Zidek }
99c99e557020775714f028b28a147edda290c783Michal Zidek
99c99e557020775714f028b28a147edda290c783Michal Zidek name = talloc_strdup(tmp_ctx, (*mc_ctx)->name);
99c99e557020775714f028b28a147edda290c783Michal Zidek if (name == NULL) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory.\n");
99c99e557020775714f028b28a147edda290c783Michal Zidek ret = ENOMEM;
99c99e557020775714f028b28a147edda290c783Michal Zidek goto done;
99c99e557020775714f028b28a147edda290c783Michal Zidek }
99c99e557020775714f028b28a147edda290c783Michal Zidek
99c99e557020775714f028b28a147edda290c783Michal Zidek type = (*mc_ctx)->type;
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce if (n_elem == (size_t)-1) {
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce n_elem = (*mc_ctx)->ft_size * 8;
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce }
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce if (timeout == (time_t)-1) {
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce timeout = (*mc_ctx)->valid_time_slot;
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce }
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce
20c2bd06b530866a3c9670e6d0da266e7279db5eMichal Zidek talloc_free(*mc_ctx);
99c99e557020775714f028b28a147edda290c783Michal Zidek
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce /* make sure we do not leave a potentially freed pointer around */
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce *mc_ctx = NULL;
0e6c9d03cacf24de4265ee0f902c216ba5a131c9Simo Sorce
99c99e557020775714f028b28a147edda290c783Michal Zidek ret = sss_mmap_cache_init(mem_ctx, name, type, n_elem, timeout, mc_ctx);
99c99e557020775714f028b28a147edda290c783Michal Zidek if (ret != EOK) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Failed to re-initialize mmap cache.\n");
99c99e557020775714f028b28a147edda290c783Michal Zidek goto done;
99c99e557020775714f028b28a147edda290c783Michal Zidek }
99c99e557020775714f028b28a147edda290c783Michal Zidek
99c99e557020775714f028b28a147edda290c783Michal Zidekdone:
99c99e557020775714f028b28a147edda290c783Michal Zidek talloc_free(tmp_ctx);
99c99e557020775714f028b28a147edda290c783Michal Zidek return ret;
99c99e557020775714f028b28a147edda290c783Michal Zidek}
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek/* Erase all contents of the mmap cache. This will bring the cache
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek * to the same state as if it was just initialized. */
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidekvoid sss_mmap_cache_reset(struct sss_mc_ctx *mc_ctx)
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek{
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek if (mc_ctx == NULL) {
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek DEBUG(SSSDBG_TRACE_FUNC,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Fastcache not initialized. Nothing to do.\n");
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek return;
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek }
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek sss_mc_header_update(mc_ctx, SSS_MC_HEADER_UNINIT);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek
677a31351c80453d9ce006481364399a96312052René Genz /* Reset the mmapped area */
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek memset(mc_ctx->data_table, 0xff, mc_ctx->dt_size);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek memset(mc_ctx->free_table, 0x00, mc_ctx->ft_size);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek memset(mc_ctx->hash_table, 0xff, mc_ctx->ht_size);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek sss_mc_header_update(mc_ctx, SSS_MC_HEADER_ALIVE);
9028706a00da1bc48547e74aa872c825ac15adb2Michal Zidek}